WIP: Deployment #3
@ -12,10 +12,13 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
with open( BASE_DIR + "/settings.json", "r") as userfile:
|
with open(BASE_DIR + "/settings.json", "r") as userfile:
|
||||||
usersettings = json.load(userfile)
|
usersettings = json.load(userfile)
|
||||||
CALIBRE_DIR = os.path.abspath(usersettings["CALIBRE_DIR"])
|
CALIBRE_DIR = os.path.abspath(usersettings["CALIBRE_DIR"])
|
||||||
SECRET_KEY = usersettings["SECRET_KEY"]
|
SECRET_KEY = usersettings["SECRET_KEY"]
|
||||||
@ -24,23 +27,21 @@ with open( BASE_DIR + "/settings.json", "r") as userfile:
|
|||||||
DEBUG = usersettings["DEBUG"]
|
DEBUG = usersettings["DEBUG"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
|
|
||||||
# optimisation stuff ###############################################3
|
# optimisation stuff ###############################################3
|
||||||
# #
|
# #
|
||||||
CONN_MAX_AGE = 60 * 5
|
CONN_MAX_AGE = 60 * 5
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
'LOCATION': 'unique-snowflake',
|
'LOCATION': 'unique-snowflake',
|
||||||
"TIMEOUT" : 60 * 5,
|
"TIMEOUT": 60 * 5,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +60,42 @@ STATICFILES_DIRS = [
|
|||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
STATIC_ROOT = BASE_DIR + "/static/"
|
STATIC_ROOT = BASE_DIR + "/static/"
|
||||||
|
## ##
|
||||||
|
#########################################################################
|
||||||
|
# LOGGING
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logfile = usersettings["LOGFILE"]
|
||||||
|
LOGGING = {
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": False,
|
||||||
|
"root": {"level": "INFO", "handlers": ["file"]},
|
||||||
|
"handlers": {
|
||||||
|
"file": {
|
||||||
|
"level": "INFO",
|
||||||
|
"class": "logging.FileHandler",
|
||||||
|
"filename": usersettings["LOGFILE"],
|
||||||
|
"formatter": "app",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"loggers": {
|
||||||
|
"django": {
|
||||||
|
"handlers": ["file"],
|
||||||
|
"level": "INFO",
|
||||||
|
"propagate": True
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"formatters": {
|
||||||
|
"app": {
|
||||||
|
"format": (
|
||||||
|
u"%(asctime)s [%(levelname)-8s] "
|
||||||
|
"(%(module)s.%(funcName)s) %(message)s"
|
||||||
|
),
|
||||||
|
"datefmt": "%Y-%m-%d %H:%M:%S",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
## ##
|
## ##
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -109,7 +146,7 @@ INSTALLED_APPS = [
|
|||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
# 'silk.middleware.SilkyMiddleware', # DEBUG/profiling purposes
|
# 'silk.middleware.SilkyMiddleware', # DEBUG/profiling purposes
|
||||||
# 'debug_toolbar.middleware.DebugToolbarMiddleware', # DEBUG purposes
|
# 'debug_toolbar.middleware.DebugToolbarMiddleware', # DEBUG purposes
|
||||||
'django.middleware.cache.UpdateCacheMiddleware', # cache
|
'django.middleware.cache.UpdateCacheMiddleware', # cache
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@ -117,7 +154,7 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'django.middleware.cache.FetchFromCacheMiddleware', # cache
|
'django.middleware.cache.FetchFromCacheMiddleware', # cache
|
||||||
]
|
]
|
||||||
## ##
|
## ##
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -163,7 +200,7 @@ DATABASES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DATABASE_ROUTERS = [ "db_routers.CalibreRouter", "db_routers.DjangoRouter"]
|
DATABASE_ROUTERS = ["db_routers.CalibreRouter", "db_routers.DjangoRouter"]
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
|
||||||
|
@ -6,9 +6,11 @@ preload_app = True # By preloading an application you can save some RAM resource
|
|||||||
keepalive = 5
|
keepalive = 5
|
||||||
# daemon = True # Detaches the server from the controlling terminal and enters the background. disabled for now
|
# daemon = True # Detaches the server from the controlling terminal and enters the background. disabled for now
|
||||||
# logging
|
# logging
|
||||||
errorlog = "/home/massiveatoms/Desktop/logs/gunicorn.log"
|
|
||||||
loglevel = "warning"
|
|
||||||
|
|
||||||
|
errorlog = "/home/massiveatoms/Desktop/logs/gunicorn_error.log"
|
||||||
|
loglevel = "warning"
|
||||||
|
accesslog = "/home/massiveatoms/Desktop/logs/gunicorn_access.log"
|
||||||
|
# capture_output = True
|
||||||
|
|
||||||
# debug settings which need to be commented out in prod
|
# debug settings which need to be commented out in prod
|
||||||
# reload=True
|
# reload=True
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"CALIBRE_DIR": "PATH\\TO\\your\\calibre\library",
|
"CALIBRE_DIR": "PATH\\TO\\your\\calibre\library",
|
||||||
"SECRET_KEY": "u(8^+rb%rz5hsx4v^^y(ul7g(4n7a8!db@s*9(m5cs*2_ppy8+",
|
"SECRET_KEY": "u(8^+rb%rz5hsx4v^^y(ul7g(4n7a8!db@s*9(m5cs*2_ppy8+",
|
||||||
"ALLOWED_HOSTS": [
|
"ALLOWED_HOSTS": [
|
||||||
"127.0.0.1"
|
"127.0.0.1"
|
||||||
],
|
],
|
||||||
"INTERNAL_IPS": [
|
"INTERNAL_IPS": [
|
||||||
"127.0.0.1"
|
"127.0.0.1"
|
||||||
]
|
],
|
||||||
|
"DEBUG" : false,
|
||||||
|
"LOGFILE" : "/home/massiveatoms/Desktop/logs/django.log"
|
||||||
}
|
}
|
55
README.md
55
README.md
@ -1,9 +1,44 @@
|
|||||||
|
# What is CalibreWebAlternative?
|
||||||
|
This is a web server to the popular book management application Calibre. We found that the builtin webserver was kinda shit, so we're building our own. (make this friendlier later)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
- navbar with tags, series, authors, etc
|
||||||
|
- Search by author, identifier, title
|
||||||
|
- authentication
|
||||||
|
|
||||||
|
|
||||||
|
# Some screenshots
|
||||||
|
Here's how the various lists look like
|
||||||
|
![booklist](./screenshots/booklist.png)
|
||||||
|
Book detail
|
||||||
|
![bookdetail](./screenshots/bookdetail.png)
|
||||||
|
navbar
|
||||||
|
![nav](./screenshots/navbar.png)
|
||||||
|
Adanced search
|
||||||
|
![booklist](./screenshots/search.png)
|
||||||
# requirements
|
# requirements
|
||||||
Django 3.0
|
Django 3.0
|
||||||
|
Calibre 4.13 (I have not tested it with anything else atm, will be resolved later)
|
||||||
|
|
||||||
# how to use:
|
# how to use:
|
||||||
EDIT `./CalibreWebCompanion/settings.json.bak`
|
1. clone repo
|
||||||
Remove the `.bak` from `db.sqlite3.bak` and `settings.json.bak`
|
2. Remove the `.bak` from `./CalibreWebCompanion/settings.json.bak` and `db.sqlite3.bak`
|
||||||
|
3. Edit `./CalibreWebCompanion/settings.json`. Definitely change the secret key
|
||||||
|
4. Not sure if the db needs to be regenerated, but we'll see later __!!!!!!!!!!__
|
||||||
|
5. pip install -r requirements.txt
|
||||||
|
6. install gunicorn and nginx
|
||||||
|
7. move this nginx.conf to /etc/nginx
|
||||||
|
8. make whatever user nginx runs as (in this case, massiveatoms) the owner of calibredir
|
||||||
|
9. give execute permissions to parent of calibredir
|
||||||
|
10. cd to repo, run `gunicorn CalibreWebCompanion.wsgi`
|
||||||
|
11. start nginx `sudo systemctl restart nginx`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`./CalibreWebCompanion`
|
`./CalibreWebCompanion`
|
||||||
run `./manage.py runserver`
|
run `./manage.py runserver`
|
||||||
|
|
||||||
@ -22,24 +57,24 @@ headless = true
|
|||||||
in `locust.conf`, and then run `./bench.py`
|
in `locust.conf`, and then run `./bench.py`
|
||||||
You can then go to [http://localhost:8089/](http://localhost:8089/) to see live graphs, tweak the number of users and more.
|
You can then go to [http://localhost:8089/](http://localhost:8089/) to see live graphs, tweak the number of users and more.
|
||||||
|
|
||||||
this is in development mode. don't actually use it or release it like this. The debug info it shows is spicy.
|
|
||||||
# Features
|
# Finished Features
|
||||||
|
|
||||||
- [x] Books
|
- [x] Books
|
||||||
- [x] navbar with tags, series, authors, etc
|
- [x] navbar with tags, series, authors, etc
|
||||||
- [x] Search
|
- [x] Search
|
||||||
- [x] authentication
|
- [x] authentication
|
||||||
- [x] Cache
|
- [x] Cache
|
||||||
- [x] Profiling with logging
|
- [x] logging
|
||||||
|
- [x] deploy instructions
|
||||||
|
|
||||||
|
# TODO ROADMAP
|
||||||
# TODO
|
|
||||||
- [ ] cache with vary headers
|
- [ ] cache with vary headers
|
||||||
- [ ] localisation
|
- [ ] localisation
|
||||||
- [ ] Beautifying template
|
- [ ] Beautifying template (only works well on 720p, no other viewports)
|
||||||
- [ ] Setup email functionality
|
- [ ] Setup email functionality
|
||||||
|
|
||||||
- [ ] deploy
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
4. move this nginx.conf to /etc/nginx
|
4. move this nginx.conf to /etc/nginx
|
||||||
5. make whatever user nginx runs as (in this case, massiveatoms) the owner of calibredir
|
5. make whatever user nginx runs as (in this case, massiveatoms) the owner of calibredir
|
||||||
6. give execute permissions to parent of calibredir
|
6. give execute permissions to parent of calibredir
|
||||||
7. cd to repo, run `gunicorn -w <2x n cores/threads> CalibreWebCompanion.wsgi`
|
7. cd to repo, run `gunicorn CalibreWebCompanion.wsgi`
|
||||||
8. start nginx `sudo systemctl restart nginx`
|
8. start nginx `sudo systemctl restart nginx`
|
||||||
|
|
||||||
Slight issues with this atm:
|
Slight issues with this atm:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
worker_processes 1;
|
worker_processes 1;
|
||||||
|
|
||||||
# user nobody nogroup;
|
# user nobody nogroup;
|
||||||
user massiveatoms; # MASSIVEATOMS
|
user massiveatoms;
|
||||||
# user nobody nobody; # for systems with 'nobody' as a group instead
|
# user nobody nobody; # for systems with 'nobody' as a group instead
|
||||||
error_log /home/massiveatoms/Desktop/logs/nginx.log warn;
|
error_log /home/massiveatoms/Desktop/logs/nginx.log warn;
|
||||||
# pid /var/run/nginx.pid;
|
# pid /var/run/nginx.pid;
|
||||||
@ -38,13 +38,13 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80 deferred; # for Linux MASSIVEATOMS
|
listen 80 deferred; # for Linux massiveatoms
|
||||||
# use 'listen 80 accept_filter=httpready;' for FreeBSD
|
# use 'listen 80 accept_filter=httpready;' for FreeBSD
|
||||||
# listen 80;
|
# listen 80;
|
||||||
client_max_body_size 4G;
|
client_max_body_size 4G;
|
||||||
|
|
||||||
# set the correct host(s) for your site
|
# set the correct host(s) for your site
|
||||||
server_name localhost www.localhost 192.168.1.4; # set this to the server url? or ip? we'll see MASSIVEATOMS
|
server_name localhost 192.168.1.4; # set this to the server url? or ip? we'll see MASSIVEATOMS
|
||||||
|
|
||||||
keepalive_timeout 5;
|
keepalive_timeout 5;
|
||||||
|
|
||||||
@ -62,13 +62,17 @@ http {
|
|||||||
location / {
|
location / {
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header Host $http_host;
|
# proxy_set_header Host $http_host;
|
||||||
# we don't want nginx trying to do something clever with
|
# we don't want nginx trying to do something clever with
|
||||||
# redirects, we set the Host: header above already.
|
# redirects, we set the Host: header above already.
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
proxy_pass http://127.0.0.1:8000;
|
proxy_pass http://127.0.0.1:8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /500.html;
|
error_page 500 502 503 504 /500.html;
|
||||||
location = /500.html {
|
location = /500.html {
|
||||||
root /path/to/app/current/public;
|
root /path/to/app/current/public;
|
||||||
|
BIN
screenshots/bookdetail.png
Normal file
BIN
screenshots/bookdetail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 288 KiB |
BIN
screenshots/booklist.png
Normal file
BIN
screenshots/booklist.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
screenshots/navbar.png
Normal file
BIN
screenshots/navbar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
BIN
screenshots/search.png
Normal file
BIN
screenshots/search.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue
Block a user