├── backup └── .gitkeep ├── apps ├── gitea │ ├── data │ │ └── .gitkeep │ └── repositories │ │ └── .gitkeep ├── plex │ └── config │ │ └── .gitkeep ├── pyload │ └── config │ │ └── .gitkeep ├── nextcloud │ ├── app │ │ ├── apps │ │ │ └── .gitkeep │ │ ├── config │ │ │ └── .gitkeep │ │ ├── themes │ │ │ └── .gitkeep │ │ └── Dockerfile │ ├── web │ │ ├── Dockerfile │ │ └── nginx.conf │ └── elasticsearch │ │ └── Dockerfile ├── home-assistant │ └── config │ │ └── .gitkeep ├── invoiceninja │ ├── app │ │ ├── logo │ │ │ └── .gitkeep │ │ └── storage │ │ │ └── .gitkeep │ └── web │ │ └── nginx.conf └── proxy │ ├── uploadsize.conf │ ├── default_location │ └── Dockerfile ├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── docker-compose.yml /backup/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/gitea/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/plex/config/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/pyload/config/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/gitea/repositories/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/nextcloud/app/apps/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/home-assistant/config/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/invoiceninja/app/logo/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/invoiceninja/app/storage/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/nextcloud/app/config/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/nextcloud/app/themes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/proxy/uploadsize.conf: -------------------------------------------------------------------------------- 1 | client_max_body_size 10G; 2 | -------------------------------------------------------------------------------- /apps/nextcloud/web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | COPY nginx.conf /etc/nginx/nginx.conf 4 | -------------------------------------------------------------------------------- /apps/proxy/default_location: -------------------------------------------------------------------------------- 1 | # do not block i-frames via X-Frame header 2 | proxy_hide_header X-Frame-Options; 3 | -------------------------------------------------------------------------------- /apps/nextcloud/elasticsearch/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM elasticsearch:6.6.2 2 | 3 | RUN bin/elasticsearch-plugin install --batch ingest-attachment 4 | -------------------------------------------------------------------------------- /apps/proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jwilder/nginx-proxy:alpine 2 | 3 | COPY uploadsize.conf /etc/nginx/conf.d/uploadsize.conf 4 | COPY default_location /etc/nginx/vhost.d/default_location 5 | -------------------------------------------------------------------------------- /apps/nextcloud/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nextcloud:fpm 2 | 3 | # install tesseract for OCR capabilities 4 | RUN set -ex; \ 5 | \ 6 | apt-get update; \ 7 | apt-get install -y --no-install-recommends \ 8 | tesseract-ocr \ 9 | tesseract-ocr-eng \ 10 | tesseract-ocr-deu \ 11 | ; \ 12 | \ 13 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 14 | rm -rf /var/lib/apt/lists/*; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /backup/* 2 | !/backup/.gitkeep 3 | # HOME ASSISTANT 4 | /apps/plex/config/* 5 | !/apps/plex/config/.gitkeep 6 | # NEXTCLOUD 7 | /apps/nextcloud/app/apps/* 8 | !/apps/nextcloud/app/apps/.gitkeep 9 | /apps/nextcloud/app/config/* 10 | !/apps/nextcloud/app/config/.gitkeep 11 | /apps/nextcloud/app/themes/* 12 | !/apps/nextcloud/app/themes/.gitkeep 13 | # HOME ASSISTANT 14 | /apps/home-assistant/config/* 15 | !/apps/home-assistant/config/.gitkeep 16 | # GITEA 17 | /apps/gitea/data/* 18 | !/apps/gitea/data/.gitkeep 19 | /apps/gitea/repositories/* 20 | !/apps/gitea/repositories/.gitkeep 21 | # INVOICENINJA 22 | /apps/invoiceninja/app/logo/* 23 | !/apps/invoiceninja/app/logo/.gitkeep 24 | /apps/invoiceninja/app/storage/* 25 | !/apps/invoiceninja/app/storage/.gitkeep 26 | # PYLOAD 27 | /apps/pyload/config/* 28 | !/apps/pyload/config/.gitkeep 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Florian Schlittenbauer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/invoiceninja/web/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | 3 | events { 4 | worker_connections 768; 5 | } 6 | 7 | http { 8 | upstream backend { 9 | server invoiceninja-app:9000; 10 | } 11 | include /etc/nginx/mime.types; 12 | default_type application/octet-stream; 13 | gzip on; 14 | gzip_disable "msie6"; 15 | 16 | server { 17 | listen 80 default; 18 | 19 | root /var/www/app/public; 20 | 21 | index index.php; 22 | 23 | charset utf-8; 24 | 25 | location / { 26 | try_files $uri $uri/ /index.php?$query_string; 27 | } 28 | 29 | location = /favicon.ico { access_log off; log_not_found off; } 30 | location = /robots.txt { access_log off; log_not_found off; } 31 | 32 | sendfile off; 33 | 34 | location ~ \.php$ { 35 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 36 | fastcgi_pass backend; 37 | fastcgi_index index.php; 38 | include fastcgi_params; 39 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 40 | fastcgi_intercept_errors off; 41 | fastcgi_buffer_size 16k; 42 | fastcgi_buffers 4 16k; 43 | } 44 | 45 | location ~ /\.ht { 46 | deny all; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARGS = $(filter-out $@,$(MAKECMDGOALS)) 2 | 3 | ############################# 4 | # ENVIRONMENT 5 | ############################# 6 | 7 | export COMPOSE_PROJECT_NAME=nas-docker 8 | export BACKUP_DIR=backup 9 | 10 | ############################# 11 | # PROJECT STATES 12 | ############################# 13 | up: 14 | docker-compose up -d --remove-orphans 15 | 16 | stop: 17 | docker-compose stop 18 | 19 | logs: 20 | docker-compose logs -f --tail=42 $(ARGS) 21 | 22 | ############################# 23 | # CONTAINER ACCESS 24 | ############################# 25 | 26 | ssh: 27 | docker exec -it -u root $$(docker-compose ps -q $(ARGS)) sh 28 | 29 | ############################# 30 | # UTILITIES 31 | ############################# 32 | 33 | update: 34 | docker-compose pull 35 | docker-compose build --pull 36 | make up 37 | 38 | nextcloud-occ: 39 | docker exec -ti -u www-data nextcloud-app php -d memory_limit=4096M /var/www/html/occ $(ARGS) 40 | 41 | nextcloud-upgrade: 42 | docker exec -u www-data nextcloud-app php -d memory_limit=4096M /var/www/html/occ upgrade 43 | docker exec -u www-data nextcloud-app php -d memory_limit=4096M /var/www/html/occ db:add-missing-indices 44 | 45 | nextcloud-maintenance-off: 46 | docker exec -u www-data nextcloud-app php -d memory_limit=4096M /var/www/html/occ maintenance:mode --off 47 | 48 | nextcloud-maintenance-on: 49 | docker exec -u www-data nextcloud-app php -d memory_limit=4096M /var/www/html/occ maintenance:mode --on 50 | 51 | ############################# 52 | # BACKUP/RESTORE 53 | ############################# 54 | backup-dbs: 55 | make nextcloud-db-backup 56 | make gitea-db-backup 57 | make hackmd-db-backup 58 | make invoiceninja-db-backup 59 | 60 | nextcloud-db-backup: 61 | docker exec $$(docker-compose ps -q nextcloud-db) mysqldump -uroot -p${NEXTCLOUD_MYSQL_ROOT_PASSWORD} --opt --single-transaction --events --all-databases --routines --comments | bzip2 > "${BACKUP_DIR}/nextcloud-db.sql.bz2" 62 | 63 | nextcloud-db-restore: 64 | make nextcloud-maintenance-on 65 | bzcat "${BACKUP_DIR}/nextcloud-db.sql.bz2" | docker exec -i $$(docker-compose ps -q nextcloud-db) mysql -u root -p${NEXTCLOUD_MYSQL_ROOT_PASSWORD} 66 | echo "FLUSH PRIVILEGES;" | docker exec -i $$(docker-compose ps -q nextcloud-db) mysql -u root -p${NEXTCLOUD_MYSQL_ROOT_PASSWORD} 67 | make nextcloud-maintenance-off 68 | make nextcloud-upgrade 69 | make nextcloud-maintenance-off 70 | 71 | gitea-db-backup: 72 | docker exec $$(docker-compose ps -q gitea-db) mysqldump -uroot -p${GITEA_MYSQL_ROOT_PASSWORD} --opt --single-transaction --events --all-databases --routines --comments | bzip2 > "${BACKUP_DIR}/gitea-db.sql.bz2" 73 | 74 | gitea-db-restore: 75 | bzcat "${BACKUP_DIR}/nextcloud-db.sql.bz2" | docker exec -i $$(docker-compose ps -q gitea-db) mysql -u root -p${GITEA_MYSQL_ROOT_PASSWORD} 76 | echo "FLUSH PRIVILEGES;" | docker exec -i $$(docker-compose ps -q gitea-db) mysql -u root -p${GITEA_MYSQL_ROOT_PASSWORD} 77 | 78 | hackmd-db-backup: 79 | docker exec $$(docker-compose ps -q hackmd-db) pg_dumpall -c -U hackmd | bzip2 > "${BACKUP_DIR}/hackmd-db.sql.bz2" 80 | 81 | hackmd-db-restore: 82 | bzcat "${BACKUP_DIR}/hackmd-db.sql.bz2" | docker exec -i $$(docker-compose ps -q hackmd-db) psql -U hackmd 83 | 84 | invoiceninja-db-backup: 85 | docker exec $$(docker-compose ps -q invoiceninja-db) mysqldump -uroot -p${INVOICENINJA_MYSQL_ROOT_PASSWORD} --opt --single-transaction --events --all-databases --routines --comments | bzip2 > "${BACKUP_DIR}/invoiceninja-db.sql.bz2" 86 | 87 | invoiceninja-db-restore: 88 | bzcat "${BACKUP_DIR}/invoiceninja-db.sql.bz2" | docker exec -i $$(docker-compose ps -q invoiceninja-db) mysql -u root -p${INVOICENINJA_MYSQL_ROOT_PASSWORD} 89 | echo "FLUSH PRIVILEGES;" | docker exec -i $$(docker-compose ps -q invoiceninja-db) mysql -u root -p${INVOICENINJA_MYSQL_ROOT_PASSWORD} 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NAS docker 2 | Repository containing the docker-compose setup for my NAS / homeserver 3 | 4 | ## Features: 5 | - [Nextcloud](https://nextcloud.com/) for convenient cloud storage 6 | - [Home Assistant](https://home-assistant.io/) for home automation and control 7 | - [Plex](https://www.plex.tv/) for movies and shows 8 | - [Nginx Proxy](https://github.com/jwilder/nginx-proxy) with [Let's Encrypt](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) for secure external access 9 | - [HackMD](https://hackmd.io/) for easy note-taking via Markdown 10 | - [Gitea](https://gitea.io/) as GIT hosting / mirroring for some of my repositories 11 | - [InvoiceNinja](https://www.invoiceninja.com/) for custom invoicing 12 | 13 | ## Environment 14 | You need to have the following environment variables setup or replaced in your `docker-compose.yml` and your storage mounted in `/mnt/storage/cloud` and `/mnt/storage/shares` for nextcloud and plex respectively. 15 | 16 | example `/etc/environment` 17 | ``` 18 | DOCKER_USER_ID=1002 19 | DOCKER_USER_GROUP_ID=1002 20 | 21 | TIMEZONE=Europe/Berlin 22 | 23 | STORAGE_PATH=/mnt/storage 24 | 25 | LETSENCRYPT_EMAIL=le@example.com 26 | 27 | PLEX_HOSTNAME=nas 28 | PLEX_ADVERTISE_IP=http://:32400/ 29 | PLEX_VIRTUAL_HOST=plex.example.com 30 | 31 | NEXTCLOUD_VIRTUAL_HOST=cloud.example.com 32 | NEXTCLOUD_MYSQL_ROOT_PASSWORD=yourRootPasswordHere 33 | NEXTCLOUD_MYSQL_PASSWORD=yourPasswordHere 34 | 35 | KIBANA_VIRTUAL_HOST=kibana.example.com 36 | 37 | HOME_ASSISTANT_VIRTUAL_HOST=hass.example.com 38 | 39 | HACKMD_VIRTUAL_HOST=hackmd.example.com 40 | HACKMD_POSTGRES_PASSWORD=yourPasswordHere 41 | 42 | GITEA_VIRTUAL_HOST=git.example.com 43 | GITEA_MYSQL_ROOT_PASSWORD=yourRootPasswordHere 44 | GITEA_MYSQL_PASSWORD=yourPasswordHere 45 | 46 | INVOICENINJA_VIRTUAL_HOST=invoice.example.com 47 | INVOICENINJA_APP_KEY=yourAppKeyHere 48 | INVOICENINJA_MYSQL_ROOT_PASSWORD=yourRootPasswordHere 49 | INVOICENINJA_MYSQL_PASSWORD=yourPasswordHere 50 | INVOICENINJA_MAIL_HOST=smtp.example.com 51 | INVOICENINJA_MAIL_USER=invoice@example.com 52 | INVOICENINJA_MAIL_PASSWORD=yourPasswordHere 53 | INVOICENINJA_MAIL_FROM_NAME=Your Name 54 | INVOICENINJA_MAIL_FROM_ADDRESS=invoice@example.com 55 | 56 | PYLOAD_VIRTUAL_HOST=downloads.example.com 57 | ``` 58 | (you need to have correct DNS records set for the domains you want to use and probably setup port forwarding of ports 80 and 443 to your nas in order to get remote access and let's encrypt working) 59 | 60 | ## Setup 61 | 1. Make sure to have `docker` and `docker-compose` installed on your system. 62 | 1. You also need to have some sort of dynamic DNS setup to your (public) IP. Point the Domain(s) you are using to this IP. 63 | 1. Add a static rule to your router for the system you are running this on, so the (private) IP doesn't change. Then forward ports `80` and `443 to this IP 64 | 1. Clone the repo to `/opt` 65 | 1. Run `docker-compose -f /opt/docker-compose.yml up -d` 66 | 1. Services should be available at the hosts specified in your environment. 67 | 68 | ## Shares 69 | As I wanted to have certain directories directly accessible in my network, I created a user `shareuser`, which owns the shared dir and used the following config for `/etc/samba/smb.conf`: 70 | ``` 71 | [global] 72 | workgroup = WORKGROUP 73 | server string = nas 74 | security = user 75 | guest ok = yes 76 | map to guest = Bad Password 77 | 78 | log file = /var/log/samba/%m.log 79 | max log size = 50 80 | printcap name = /dev/null 81 | load printers = no 82 | 83 | # Samba Shares 84 | [nas] 85 | comment = Storage on NAS 86 | path = /mnt/storage/shares 87 | browseable = yes 88 | public = yes 89 | writeable = yes 90 | create mask = 0644 91 | directory mask = 0755 92 | force user = shareuser 93 | ``` 94 | *You will need to restart samba for config changes to take effect* 95 | -------------------------------------------------------------------------------- /apps/nextcloud/web/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | 3 | error_log /var/log/nginx/error.log warn; 4 | pid /var/run/nginx.pid; 5 | 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | 12 | http { 13 | include /etc/nginx/mime.types; 14 | default_type application/octet-stream; 15 | 16 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 17 | '$status $body_bytes_sent "$http_referer" ' 18 | '"$http_user_agent" "$http_x_forwarded_for"'; 19 | 20 | access_log /var/log/nginx/access.log main; 21 | 22 | sendfile on; 23 | #tcp_nopush on; 24 | 25 | keepalive_timeout 65; 26 | 27 | set_real_ip_from 10.0.0.0/8; 28 | set_real_ip_from 172.16.0.0/12; 29 | set_real_ip_from 192.168.0.0/16; 30 | real_ip_header X-Real-IP; 31 | 32 | #gzip on; 33 | 34 | upstream php-handler { 35 | server nextcloud-app:9000; 36 | } 37 | 38 | server { 39 | listen 80; 40 | 41 | # Add headers to serve security related headers 42 | # Before enabling Strict-Transport-Security headers please read into this 43 | # topic first. 44 | # add_header Strict-Transport-Security "max-age=15768000; 45 | # includeSubDomains; preload;"; 46 | # 47 | # WARNING: Only add the preload option once you read about 48 | # the consequences in https://hstspreload.org/. This option 49 | # will add the domain to a hardcoded list that is shipped 50 | # in all major browsers and getting removed from this list 51 | # could take several months. 52 | add_header X-Content-Type-Options nosniff; 53 | add_header X-XSS-Protection "1; mode=block"; 54 | add_header X-Robots-Tag none; 55 | add_header X-Download-Options noopen; 56 | add_header X-Permitted-Cross-Domain-Policies none; 57 | add_header Referrer-Policy no-referrer; 58 | 59 | root /var/www/html; 60 | 61 | location = /robots.txt { 62 | allow all; 63 | log_not_found off; 64 | access_log off; 65 | } 66 | 67 | # The following 2 rules are only needed for the user_webfinger app. 68 | # Uncomment it if you're planning to use this app. 69 | #rewrite ^/.well-known/host-meta /public.php?service=host-meta last; 70 | #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json 71 | # last; 72 | 73 | location = /.well-known/carddav { 74 | return 301 $scheme://$host/remote.php/dav; 75 | } 76 | location = /.well-known/caldav { 77 | return 301 $scheme://$host/remote.php/dav; 78 | } 79 | 80 | # set max upload size 81 | client_max_body_size 10G; 82 | fastcgi_buffers 64 4K; 83 | 84 | # Enable gzip but do not remove ETag headers 85 | gzip on; 86 | gzip_vary on; 87 | gzip_comp_level 4; 88 | gzip_min_length 256; 89 | gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; 90 | gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; 91 | 92 | # Uncomment if your server is build with the ngx_pagespeed module 93 | # This module is currently not supported. 94 | #pagespeed off; 95 | 96 | location / { 97 | rewrite ^ /index.php$request_uri; 98 | } 99 | 100 | location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { 101 | deny all; 102 | } 103 | location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { 104 | deny all; 105 | } 106 | 107 | location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) { 108 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 109 | include fastcgi_params; 110 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 111 | fastcgi_param PATH_INFO $fastcgi_path_info; 112 | # fastcgi_param HTTPS on; 113 | #Avoid sending the security headers twice 114 | fastcgi_param modHeadersAvailable true; 115 | fastcgi_param front_controller_active true; 116 | fastcgi_pass php-handler; 117 | fastcgi_intercept_errors on; 118 | fastcgi_request_buffering off; 119 | } 120 | 121 | location ~ ^/(?:updater|ocs-provider)(?:$|/) { 122 | try_files $uri/ =404; 123 | index index.php; 124 | } 125 | 126 | # Adding the cache control header for js and css files 127 | # Make sure it is BELOW the PHP block 128 | location ~ \.(?:css|js|woff2?|svg|gif)$ { 129 | try_files $uri /index.php$request_uri; 130 | add_header Cache-Control "public, max-age=15778463"; 131 | # Add headers to serve security related headers (It is intended to 132 | # have those duplicated to the ones above) 133 | # Before enabling Strict-Transport-Security headers please read into 134 | # this topic first. 135 | # add_header Strict-Transport-Security "max-age=15768000; 136 | # includeSubDomains; preload;"; 137 | # 138 | # WARNING: Only add the preload option once you read about 139 | # the consequences in https://hstspreload.org/. This option 140 | # will add the domain to a hardcoded list that is shipped 141 | # in all major browsers and getting removed from this list 142 | # could take several months. 143 | add_header X-Content-Type-Options nosniff; 144 | add_header X-XSS-Protection "1; mode=block"; 145 | add_header X-Robots-Tag none; 146 | add_header X-Download-Options noopen; 147 | add_header X-Permitted-Cross-Domain-Policies none; 148 | add_header Referrer-Policy no-referrer; 149 | 150 | # Optional: Don't log access to assets 151 | access_log off; 152 | } 153 | 154 | location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ { 155 | try_files $uri /index.php$request_uri; 156 | # Optional: Don't log access to other assets 157 | access_log off; 158 | } 159 | 160 | # collabora static files 161 | location ^~ /loleaflet { 162 | proxy_pass https://collabora:9980; 163 | proxy_set_header Host $http_host; 164 | } 165 | 166 | # collabora WOPI discovery URL 167 | location ^~ /hosting/discovery { 168 | proxy_pass https://collabora:9980; 169 | proxy_set_header Host $http_host; 170 | } 171 | 172 | # collabora websockets, download, presentation and image upload 173 | location ^~ /lool { 174 | proxy_pass https://collabora:9980; 175 | proxy_set_header Upgrade $http_upgrade; 176 | proxy_set_header Connection "upgrade"; 177 | proxy_set_header Host $http_host; 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | #-----------------------------------# 5 | # PROXY # 6 | #-----------------------------------# 7 | proxy: 8 | build: ./apps/proxy 9 | container_name: proxy 10 | labels: 11 | com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true" 12 | ports: 13 | - 80:80 14 | - 443:443 15 | networks: 16 | - proxy-tier 17 | restart: unless-stopped 18 | volumes: 19 | - proxy-certs:/etc/nginx/certs:ro 20 | - proxy-conf:/etc/nginx/conf.d 21 | - proxy-vhost:/etc/nginx/vhost.d 22 | - proxy-html:/usr/share/nginx/html 23 | - /var/run/docker.sock:/tmp/docker.sock:ro 24 | 25 | 26 | #-----------------------------------# 27 | # LETSENCRYPT # 28 | #-----------------------------------# 29 | letsencrypt: 30 | image: jrcs/letsencrypt-nginx-proxy-companion 31 | container_name: letsencrypt 32 | networks: 33 | - proxy-tier 34 | restart: unless-stopped 35 | volumes: 36 | - proxy-certs:/etc/nginx/certs 37 | - proxy-conf:/etc/nginx/conf.d 38 | - proxy-vhost:/etc/nginx/vhost.d 39 | - proxy-html:/usr/share/nginx/html 40 | - /var/run/docker.sock:/var/run/docker.sock:ro 41 | 42 | 43 | #-----------------------------------# 44 | # PLEX # 45 | #-----------------------------------# 46 | plex: 47 | image: plexinc/pms-docker 48 | container_name: plex 49 | ports: 50 | - 32400:32400/tcp 51 | - 3005:3005/tcp 52 | - 8324:8324/tcp 53 | - 32469:32469/tcp 54 | - 1900:1900/udp 55 | - 32410:32410/udp 56 | - 32412:32412/udp 57 | - 32413:32413/udp 58 | - 32414:32414/udp 59 | networks: 60 | - proxy-tier 61 | - default 62 | restart: unless-stopped 63 | volumes: 64 | - ./apps/plex/config:/config 65 | - ${STORAGE_PATH}/shares:/data 66 | tmpfs: 67 | - /tmp 68 | - /transcode 69 | hostname: ${PLEX_HOSTNAME} 70 | environment: 71 | - PUID=${DOCKER_USER_ID} 72 | - PGID=${DOCKER_USER_GROUP_ID} 73 | - TZ=${TIMEZONE} 74 | - ADVERTISE_IP=${PLEX_ADVERTISE_IP} 75 | - VIRTUAL_HOST=${PLEX_HOSTNAME},${PLEX_VIRTUAL_HOST} 76 | - VIRTUAL_PORT=32400 77 | - LETSENCRYPT_HOST=${PLEX_VIRTUAL_HOST} 78 | - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} 79 | 80 | 81 | #-----------------------------------# 82 | # NEXTCLOUD # 83 | #-----------------------------------# 84 | nextcloud-db: 85 | image: mariadb 86 | container_name: nextcloud-db 87 | networks: 88 | - proxy-tier 89 | restart: unless-stopped 90 | volumes: 91 | - nextcloud-db:/var/lib/mysql 92 | environment: 93 | - MYSQL_ROOT_PASSWORD=${NEXTCLOUD_MYSQL_ROOT_PASSWORD} 94 | - MYSQL_DATABASE=nextcloud 95 | - MYSQL_USER=nextcloud 96 | - MYSQL_PASSWORD=${NEXTCLOUD_MYSQL_PASSWORD} 97 | command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW 98 | 99 | nextcloud-app: 100 | build: ./apps/nextcloud/app 101 | container_name: nextcloud-app 102 | networks: 103 | - proxy-tier 104 | restart: unless-stopped 105 | volumes: 106 | - nextcloud-core:/var/www/html 107 | - ./apps/nextcloud/app/apps:/var/www/html/apps 108 | - ./apps/nextcloud/app/config:/var/www/html/config 109 | - ./apps/nextcloud/app/themes:/var/www/html/themes 110 | - ${STORAGE_PATH}/cloud:/var/www/html/data 111 | environment: 112 | - MYSQL_HOST=nextcloud-db 113 | - MYSQL_ROOT_PASSWORD=${NEXTCLOUD_MYSQL_ROOT_PASSWORD} 114 | - MYSQL_DATABASE=nextcloud 115 | - MYSQL_USER=nextcloud 116 | - MYSQL_PASSWORD=${NEXTCLOUD_MYSQL_PASSWORD} 117 | - REDIS_HOST=redis 118 | depends_on: 119 | - nextcloud-db 120 | - redis 121 | - elasticsearch 122 | links: 123 | - nextcloud-db 124 | - redis 125 | - elasticsearch 126 | 127 | nextcloud-web: 128 | build: ./apps/nextcloud/web 129 | container_name: nextcloud-web 130 | networks: 131 | - proxy-tier 132 | - default 133 | restart: unless-stopped 134 | volumes: 135 | - nextcloud-core:/var/www/html:ro 136 | - ./apps/nextcloud/app/apps:/var/www/html/apps:ro 137 | - ./apps/nextcloud/app/config:/var/www/html/config:ro 138 | - ./apps/nextcloud/app/themes:/var/www/html/themes:ro 139 | - ${STORAGE_PATH}/cloud:/var/www/html/data:ro 140 | environment: 141 | - VIRTUAL_HOST=${NEXTCLOUD_VIRTUAL_HOST} 142 | - VIRTUAL_PORT=80 143 | - LETSENCRYPT_HOST=${NEXTCLOUD_VIRTUAL_HOST} 144 | - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} 145 | depends_on: 146 | - nextcloud-app 147 | - collabora 148 | links: 149 | - nextcloud-app 150 | - collabora 151 | 152 | nextcloud-cron: 153 | build: ./apps/nextcloud/app 154 | container_name: nextcloud-cron 155 | restart: unless-stopped 156 | volumes: 157 | - nextcloud-core:/var/www/html 158 | - ./apps/nextcloud/app/apps:/var/www/html/apps 159 | - ./apps/nextcloud/app/config:/var/www/html/config 160 | - ./apps/nextcloud/app/themes:/var/www/html/themes 161 | - ${STORAGE_PATH}/cloud:/var/www/html/data 162 | user: www-data 163 | entrypoint: /cron.sh 164 | depends_on: 165 | - nextcloud-db 166 | - redis 167 | - elasticsearch 168 | links: 169 | - nextcloud-db 170 | - redis 171 | - elasticsearch 172 | 173 | redis: 174 | image: redis 175 | container_name: redis 176 | networks: 177 | - proxy-tier 178 | - default 179 | restart: unless-stopped 180 | 181 | collabora: 182 | image: collabora/code 183 | container_name: collabora 184 | cap_add: 185 | - MKNOD 186 | networks: 187 | - proxy-tier 188 | restart: unless-stopped 189 | environment: 190 | - domain=${NEXTCLOUD_VIRTUAL_HOST} 191 | 192 | elasticsearch: 193 | build: ./apps/nextcloud/elasticsearch 194 | container_name: elasticsearch 195 | networks: 196 | - proxy-tier 197 | restart: unless-stopped 198 | volumes: 199 | - elasticsearch:/usr/share/elasticsearch/data 200 | environment: 201 | - discovery.type=single-node 202 | 203 | # kibana: 204 | # image: docker.elastic.co/kibana/kibana:6.6.2 205 | # container_name: kibana 206 | # networks: 207 | # - proxy-tier 208 | # restart: unless-stopped 209 | # environment: 210 | # - "ELASTICSEARCH_URL=http://elasticsearch:9200" 211 | # - VIRTUAL_HOST=${KIBANA_VIRTUAL_HOST} 212 | # - VIRTUAL_PORT=80 213 | # - LETSENCRYPT_HOST=${KIBANA_VIRTUAL_HOST} 214 | # - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} 215 | # depends_on: 216 | # - elasticsearch 217 | # links: 218 | # - elasticsearch 219 | 220 | 221 | #-----------------------------------# 222 | # HACKMD # 223 | #-----------------------------------# 224 | hackmd-db: 225 | image: postgres:10-alpine 226 | container_name: hackmd-db 227 | networks: 228 | - proxy-tier 229 | restart: unless-stopped 230 | volumes: 231 | - hackmd-db:/var/lib/postgresql/data 232 | environment: 233 | - POSTGRES_USER=hackmd 234 | - POSTGRES_PASSWORD=${HACKMD_POSTGRES_PASSWORD} 235 | - POSTGRES_DB=hackmd 236 | 237 | hackmd-app: 238 | image: hackmdio/hackmd:alpine 239 | container_name: hackmd-app 240 | networks: 241 | - proxy-tier 242 | restart: unless-stopped 243 | environment: 244 | - HMD_DB_URL=postgres://hackmd:${HACKMD_POSTGRES_PASSWORD}@hackmd-db:5432/hackmd 245 | - HMD_USECDN=false 246 | - HMD_ALLOW_EMAIL_REGISTER=false 247 | - HMD_ALLOW_ANONYMOUS=false 248 | - HMD_ALLOW_PDF_EXPORT=true 249 | - VIRTUAL_HOST=${HACKMD_VIRTUAL_HOST} 250 | - VIRTUAL_PORT=3000 251 | - LETSENCRYPT_HOST=${HACKMD_VIRTUAL_HOST} 252 | - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} 253 | depends_on: 254 | - hackmd-db 255 | links: 256 | - hackmd-db 257 | 258 | 259 | #-----------------------------------# 260 | # GITEA # 261 | #-----------------------------------# 262 | gitea-app: 263 | image: gitea/gitea 264 | container_name: gitea-app 265 | ports: 266 | - 222:22 267 | networks: 268 | - proxy-tier 269 | - default 270 | restart: unless-stopped 271 | volumes: 272 | - ./apps/gitea/data:/data 273 | - ./apps/gitea/repositories:/var/lib/gitea/repositories 274 | - ./backup/gitea:/backup 275 | environment: 276 | - VIRTUAL_HOST=${GITEA_VIRTUAL_HOST} 277 | - VIRTUAL_PORT=3000 278 | - LETSENCRYPT_HOST=${GITEA_VIRTUAL_HOST} 279 | - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} 280 | - DB_TYPE=mysql 281 | - DB_HOST=gitea-db:3306 282 | - DB_NAME=gitea 283 | - DB_USER=gitea 284 | - DB_PASSWD=${GITEA_MYSQL_PASSWORD} 285 | depends_on: 286 | - gitea-db 287 | links: 288 | - gitea-db 289 | 290 | gitea-db: 291 | image: mariadb 292 | container_name: gitea-db 293 | networks: 294 | - proxy-tier 295 | - default 296 | restart: unless-stopped 297 | volumes: 298 | - gitea-db:/var/lib/mysql 299 | environment: 300 | - MYSQL_ROOT_PASSWORD=${GITEA_MYSQL_ROOT_PASSWORD} 301 | - MYSQL_DATABASE=gitea 302 | - MYSQL_USER=gitea 303 | - MYSQL_PASSWORD=${GITEA_MYSQL_PASSWORD} 304 | 305 | 306 | #-----------------------------------# 307 | # INVOICENINJA # 308 | #-----------------------------------# 309 | invoiceninja-app: 310 | image: invoiceninja/invoiceninja 311 | container_name: invoiceninja-app 312 | networks: 313 | - proxy-tier 314 | restart: unless-stopped 315 | volumes: 316 | - invoiceninja-public:/var/www/app/public:rw 317 | - ./apps/invoiceninja/app/storage:/var/www/app/storage:rw 318 | - ./apps/invoiceninja/app/logo:/var/www/app/public/logo:rw 319 | environment: 320 | - TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" 321 | - REQUIRE_HTTPS=true" 322 | - APP_DEBUG=0 323 | - APP_URL=https://${INVOICENINJA_VIRTUAL_HOST} 324 | - APP_KEY=${INVOICENINJA_APP_KEY} 325 | - APP_CIPHER=AES-256-CBC 326 | - DB_USERNAME=ninja 327 | - DB_PASSWORD=${INVOICENINJA_MYSQL_PASSWORD} 328 | - DB_HOST=invoiceninja-db 329 | - DB_DATABASE=ninja 330 | - MAIL_HOST=${INVOICENINJA_MAIL_HOST} 331 | - MAIL_USERNAME=${INVOICENINJA_MAIL_USER} 332 | - MAIL_PASSWORD=${INVOICENINJA_MAIL_PASSWORD} 333 | - MAIL_DRIVER=smtp 334 | - MAIL_FROM_NAME="${INVOICENINJA_MAIL_FROM_NAME}" 335 | - MAIL_FROM_ADDRESS=${INVOICENINJA_MAIL_FROM_ADDRESS} 336 | depends_on: 337 | - invoiceninja-db 338 | links: 339 | - invoiceninja-db 340 | 341 | invoiceninja-cron: 342 | image: invoiceninja/invoiceninja 343 | container_name: invoiceninja-cron 344 | networks: 345 | - proxy-tier 346 | restart: unless-stopped 347 | volumes: 348 | - invoiceninja-public:/var/www/app/public:rw 349 | - ./apps/invoiceninja/app/storage:/var/www/app/storage:rw 350 | - ./apps/invoiceninja/app/logo:/var/www/app/public/logo:rw 351 | environment: 352 | - TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" 353 | - REQUIRE_HTTPS=true 354 | - APP_DEBUG=0 355 | - APP_URL=https://${INVOICENINJA_VIRTUAL_HOST} 356 | - APP_KEY=${INVOICENINJA_APP_KEY} 357 | - APP_CIPHER=AES-256-CBC 358 | - DB_USERNAME=ninja 359 | - DB_PASSWORD=${INVOICENINJA_MYSQL_PASSWORD} 360 | - DB_HOST=invoiceninja-db 361 | - DB_DATABASE=ninja 362 | - MAIL_HOST=${INVOICENINJA_MAIL_HOST} 363 | - MAIL_USERNAME=${INVOICENINJA_MAIL_USER} 364 | - MAIL_PASSWORD=${INVOICENINJA_MAIL_PASSWORD} 365 | - MAIL_DRIVER=smtp 366 | - MAIL_FROM_NAME="${INVOICENINJA_MAIL_FROM_NAME}" 367 | - MAIL_FROM_ADDRESS=${INVOICENINJA_MAIL_FROM_ADDRESS} 368 | depends_on: 369 | - invoiceninja-db 370 | links: 371 | - invoiceninja-db 372 | entrypoint: | 373 | bash -c 'bash -s <