mirror of
https://github.com/caronc/apprise-api.git
synced 2024-12-13 10:21:14 +01:00
Better non-root permission handling (#55)
This commit is contained in:
parent
ddb209264b
commit
e65b80cb11
22
Dockerfile
22
Dockerfile
@ -21,32 +21,28 @@ RUN apt-get update -qq && \
|
|||||||
COPY ./requirements.txt /etc/requirements.txt
|
COPY ./requirements.txt /etc/requirements.txt
|
||||||
RUN pip3 install -q -r /etc/requirements.txt gunicorn
|
RUN pip3 install -q -r /etc/requirements.txt gunicorn
|
||||||
|
|
||||||
# Nginx configuration
|
|
||||||
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
|
|
||||||
COPY /etc/nginx.conf /etc/nginx/conf.d/nginx.conf
|
|
||||||
|
|
||||||
# Copy our static content in place
|
# Copy our static content in place
|
||||||
COPY apprise_api/static /usr/share/nginx/html/s/
|
COPY apprise_api/static /usr/share/nginx/html/s/
|
||||||
|
|
||||||
# Supervisor configuration
|
|
||||||
COPY /etc/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
|
||||||
|
|
||||||
# set work directory
|
# set work directory
|
||||||
WORKDIR /opt/apprise
|
WORKDIR /opt/apprise
|
||||||
|
|
||||||
# Copy over Apprise API
|
# Copy over Apprise API
|
||||||
COPY apprise_api/ webapp
|
COPY apprise_api/ webapp
|
||||||
|
|
||||||
# Change port of gunicorn
|
|
||||||
RUN sed -i -e 's/:8000/:8080/g' /opt/apprise/webapp/gunicorn.conf.py
|
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
RUN apt-get remove -y -qq build-essential libffi-dev libssl-dev python-dev && \
|
RUN apt-get remove -y -qq build-essential libffi-dev libssl-dev python-dev && \
|
||||||
apt-get clean autoclean && \
|
apt-get clean autoclean && \
|
||||||
apt-get autoremove --yes && \
|
apt-get autoremove --yes && \
|
||||||
rm -rf /var/lib/{apt,dpkg,cache,log}/
|
rm -rf /var/lib/{apt,dpkg,cache,log}/
|
||||||
|
|
||||||
EXPOSE 8000
|
# Configuration Permissions (to run nginx as a non-root user)
|
||||||
VOLUME /config
|
RUN umask 0002 && \
|
||||||
|
mkdir -p /config /run/apprise && \
|
||||||
|
chown www-data:www-data -R /run/apprise /var/lib/nginx /config
|
||||||
|
|
||||||
CMD ["/usr/bin/supervisord"]
|
# Handle running as a non-root user (www-data is id/gid 33)
|
||||||
|
USER www-data
|
||||||
|
VOLUME /config
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["/usr/bin/supervisord", "-c", "/opt/apprise/webapp/etc/supervisord.conf"]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Take advantage of [Apprise](https://github.com/caronc/apprise) through your network with a user-friendly API.
|
Take advantage of [Apprise](https://github.com/caronc/apprise) through your network with a user-friendly API.
|
||||||
|
|
||||||
- Send notifications to more then 65+ services.
|
- Send notifications to more then 70+ services.
|
||||||
- An incredibly lightweight gateway to Apprise.
|
- An incredibly lightweight gateway to Apprise.
|
||||||
- A production ready micro-service at your disposal.
|
- A production ready micro-service at your disposal.
|
||||||
|
|
||||||
@ -51,6 +51,7 @@ A `docker-compose.yml` file is already set up to grant you an instant production
|
|||||||
docker-compose up
|
docker-compose up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Config Directory Permissions
|
### Config Directory Permissions
|
||||||
Under the hood, An NginX services is reading/writing your configuration files as the user (and group) `www-data` which generally has the id of `33`. In preparation so that you don't get the error: `An error occured saving configuration.` consider also setting up your local `/var/lib/apprise/config` permissions as:
|
Under the hood, An NginX services is reading/writing your configuration files as the user (and group) `www-data` which generally has the id of `33`. In preparation so that you don't get the error: `An error occured saving configuration.` consider also setting up your local `/var/lib/apprise/config` permissions as:
|
||||||
|
|
||||||
|
@ -107,6 +107,19 @@ class AddTests(SimpleTestCase):
|
|||||||
)
|
)
|
||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
# Test the handling of underlining disk/write exceptions
|
||||||
|
with patch('os.makedirs') as mock_mkdirs:
|
||||||
|
mock_mkdirs.side_effect = OSError()
|
||||||
|
# We'll fail to write our key now
|
||||||
|
response = self.client.post(
|
||||||
|
'/add/{}'.format(key),
|
||||||
|
data=json.dumps({'urls': 'mailto://user:pass@yahoo.ca'}),
|
||||||
|
content_type='application/json',
|
||||||
|
)
|
||||||
|
|
||||||
|
# internal errors are correctly identified
|
||||||
|
assert response.status_code == 500
|
||||||
|
|
||||||
# Test the handling of underlining disk/write exceptions
|
# Test the handling of underlining disk/write exceptions
|
||||||
with patch('gzip.open') as mock_open:
|
with patch('gzip.open') as mock_open:
|
||||||
mock_open.side_effect = OSError()
|
mock_open.side_effect = OSError()
|
||||||
|
@ -36,7 +36,7 @@ from django.conf import settings
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
# Get an instance of a logger
|
# Get an instance of a logger
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger('django')
|
||||||
|
|
||||||
|
|
||||||
class AppriseStoreMode(object):
|
class AppriseStoreMode(object):
|
||||||
@ -120,8 +120,14 @@ class AppriseConfigCache(object):
|
|||||||
|
|
||||||
# First two characters are reserved for cache level directory writing.
|
# First two characters are reserved for cache level directory writing.
|
||||||
path, filename = self.path(key)
|
path, filename = self.path(key)
|
||||||
|
try:
|
||||||
os.makedirs(path, exist_ok=True)
|
os.makedirs(path, exist_ok=True)
|
||||||
|
|
||||||
|
except OSError:
|
||||||
|
# Permission error
|
||||||
|
logger.error('Could not create directory {}'.format(path))
|
||||||
|
return False
|
||||||
|
|
||||||
# Write our file to a temporary file
|
# Write our file to a temporary file
|
||||||
_, tmp_path = tempfile.mkstemp(suffix='.tmp', dir=path)
|
_, tmp_path = tempfile.mkstemp(suffix='.tmp', dir=path)
|
||||||
if self.mode == AppriseStoreMode.HASH:
|
if self.mode == AppriseStoreMode.HASH:
|
||||||
|
73
apprise_api/etc/nginx.conf
Normal file
73
apprise_api/etc/nginx.conf
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
daemon off;
|
||||||
|
worker_processes auto;
|
||||||
|
pid /run/apprise/nginx.pid;
|
||||||
|
include /etc/nginx/modules-enabled/*.conf;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 768;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
##
|
||||||
|
# Basic Settings
|
||||||
|
##
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
##
|
||||||
|
# SSL Settings
|
||||||
|
##
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Logging Settings
|
||||||
|
##
|
||||||
|
access_log /dev/stdout;
|
||||||
|
error_log /dev/stdout info;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Gzip Settings
|
||||||
|
##
|
||||||
|
gzip on;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Host Configuration
|
||||||
|
##
|
||||||
|
client_body_buffer_size 256k;
|
||||||
|
client_body_in_file_only off;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8000;
|
||||||
|
|
||||||
|
# Main Website
|
||||||
|
location / {
|
||||||
|
include /etc/nginx/uwsgi_params;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_pass http://localhost:8080;
|
||||||
|
# Give ample time for notifications to fire
|
||||||
|
proxy_read_timeout 120s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static Content
|
||||||
|
location /s/ {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 404 error handling
|
||||||
|
error_page 404 /404.html;
|
||||||
|
|
||||||
|
# redirect server error pages to the static page /50x.html
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,19 @@
|
|||||||
[supervisord]
|
[supervisord]
|
||||||
nodaemon=true
|
nodaemon=true
|
||||||
|
pidfile=/run/apprise/supervisord.pid
|
||||||
|
logfile=/dev/null
|
||||||
|
logfile_maxbytes=0
|
||||||
|
user=www-data
|
||||||
|
|
||||||
[program:nginx]
|
[program:nginx]
|
||||||
command=/usr/sbin/nginx
|
command=/usr/sbin/nginx -c /opt/apprise/webapp/etc/nginx.conf
|
||||||
stdout_logfile=/dev/stdout
|
stdout_logfile=/dev/stdout
|
||||||
stdout_logfile_maxbytes=0
|
stdout_logfile_maxbytes=0
|
||||||
stderr_logfile=/dev/stderr
|
stderr_logfile=/dev/stderr
|
||||||
stderr_logfile_maxbytes=0
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
[program:gunicorn]
|
[program:gunicorn]
|
||||||
command=gunicorn -c /opt/apprise/webapp/gunicorn.conf.py --worker-tmp-dir /dev/shm core.wsgi
|
command=gunicorn -c /opt/apprise/webapp/gunicorn.conf.py -b :8080 --worker-tmp-dir /dev/shm core.wsgi
|
||||||
user=www-data
|
|
||||||
directory=/opt/apprise/webapp
|
directory=/opt/apprise/webapp
|
||||||
stdout_logfile=/dev/stdout
|
stdout_logfile=/dev/stdout
|
||||||
stdout_logfile_maxbytes=0
|
stdout_logfile_maxbytes=0
|
@ -6,3 +6,12 @@ services:
|
|||||||
container_name: apprise
|
container_name: apprise
|
||||||
ports:
|
ports:
|
||||||
- 8000:8000
|
- 8000:8000
|
||||||
|
user: "www-data:www-data"
|
||||||
|
volumes:
|
||||||
|
- ./apprise_api:/opt/apprise/webapp:ro
|
||||||
|
# if uncommenting the below, you will need to type the following
|
||||||
|
# otherwise the django instance won't have permissions to write
|
||||||
|
# to the directory correctly:
|
||||||
|
# $> chown -R 33:33 ./config
|
||||||
|
# $> chmod -R 775 ./config
|
||||||
|
# - ./config:/config:rw
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 8000;
|
|
||||||
|
|
||||||
# Main Website
|
|
||||||
location / {
|
|
||||||
include uwsgi_params;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_pass http://localhost:8080;
|
|
||||||
# Give ample time for notifications to fire
|
|
||||||
proxy_read_timeout 120s;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Static Content
|
|
||||||
location /s/ {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 404 error handling
|
|
||||||
error_page 404 /404.html;
|
|
||||||
|
|
||||||
# redirect server error pages to the static page /50x.html
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user