WIP: Deployment #3
@ -12,10 +12,13 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
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)
|
||||
CALIBRE_DIR = os.path.abspath(usersettings["CALIBRE_DIR"])
|
||||
SECRET_KEY = usersettings["SECRET_KEY"]
|
||||
@ -24,23 +27,21 @@ with open( BASE_DIR + "/settings.json", "r") as userfile:
|
||||
DEBUG = usersettings["DEBUG"]
|
||||
|
||||
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
|
||||
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
||||
# optimisation stuff ###############################################3
|
||||
# #
|
||||
CONN_MAX_AGE = 60 * 5
|
||||
CONN_MAX_AGE = 60 * 5
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'LOCATION': 'unique-snowflake',
|
||||
"TIMEOUT" : 60 * 5,
|
||||
|
||||
"TIMEOUT": 60 * 5,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +60,42 @@ STATICFILES_DIRS = [
|
||||
STATIC_URL = '/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 = [
|
||||
# 'silk.middleware.SilkyMiddleware', # DEBUG/profiling purposes
|
||||
# 'debug_toolbar.middleware.DebugToolbarMiddleware', # DEBUG purposes
|
||||
'django.middleware.cache.UpdateCacheMiddleware', # cache
|
||||
'django.middleware.cache.UpdateCacheMiddleware', # cache
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
@ -117,7 +154,7 @@ MIDDLEWARE = [
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'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
|
||||
# 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
|
||||
# daemon = True # Detaches the server from the controlling terminal and enters the background. disabled for now
|
||||
# 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
|
||||
# reload=True
|
||||
|
@ -1,10 +1,12 @@
|
||||
{
|
||||
"CALIBRE_DIR": "PATH\\TO\\your\\calibre\library",
|
||||
"SECRET_KEY": "u(8^+rb%rz5hsx4v^^y(ul7g(4n7a8!db@s*9(m5cs*2_ppy8+",
|
||||
"ALLOWED_HOSTS": [
|
||||
"ALLOWED_HOSTS": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"INTERNAL_IPS": [
|
||||
"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
|
||||
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:
|
||||
EDIT `./CalibreWebCompanion/settings.json.bak`
|
||||
Remove the `.bak` from `db.sqlite3.bak` and `settings.json.bak`
|
||||
1. clone repo
|
||||
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`
|
||||
run `./manage.py runserver`
|
||||
|
||||
@ -22,24 +57,24 @@ headless = true
|
||||
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.
|
||||
|
||||
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] navbar with tags, series, authors, etc
|
||||
- [x] Search
|
||||
- [x] authentication
|
||||
- [x] Cache
|
||||
- [x] Profiling with logging
|
||||
- [x] logging
|
||||
- [x] deploy instructions
|
||||
|
||||
|
||||
# TODO
|
||||
# TODO ROADMAP
|
||||
- [ ] cache with vary headers
|
||||
- [ ] localisation
|
||||
- [ ] Beautifying template
|
||||
- [ ] Beautifying template (only works well on 720p, no other viewports)
|
||||
- [ ] Setup email functionality
|
||||
|
||||
- [ ] deploy
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
4. move this nginx.conf to /etc/nginx
|
||||
5. make whatever user nginx runs as (in this case, massiveatoms) the owner 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`
|
||||
|
||||
Slight issues with this atm:
|
||||
|
@ -1,7 +1,7 @@
|
||||
worker_processes 1;
|
||||
|
||||
# user nobody nogroup;
|
||||
user massiveatoms; # MASSIVEATOMS
|
||||
user massiveatoms;
|
||||
# user nobody nobody; # for systems with 'nobody' as a group instead
|
||||
error_log /home/massiveatoms/Desktop/logs/nginx.log warn;
|
||||
# pid /var/run/nginx.pid;
|
||||
@ -38,13 +38,13 @@ http {
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 deferred; # for Linux MASSIVEATOMS
|
||||
listen 80 deferred; # for Linux massiveatoms
|
||||
# use 'listen 80 accept_filter=httpready;' for FreeBSD
|
||||
# listen 80;
|
||||
client_max_body_size 4G;
|
||||
|
||||
# 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;
|
||||
|
||||
@ -62,13 +62,17 @@ http {
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
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
|
||||
# redirects, we set the Host: header above already.
|
||||
proxy_redirect off;
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
error_page 500 502 503 504 /500.html;
|
||||
location = /500.html {
|
||||
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