aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeonXP <i@neonxp.dev>2023-02-19 00:27:14 +0300
committerNeonXP <i@neonxp.dev>2023-02-19 00:27:14 +0300
commit26391945013bbcb647568da54be967e156f89032 (patch)
tree461cfa51a80fece21fe72c19d5a072877aaabf2b
initialHEADmaster
-rw-r--r--.env.dist8
-rw-r--r--.gitignore1
-rw-r--r--README.md55
-rw-r--r--docker-compose.yml238
-rw-r--r--etc/Caddyfile101
-rw-r--r--etc/init.sql4
-rw-r--r--minidlna/Dockerfile13
-rwxr-xr-xminidlna/entrypoint.sh62
-rwxr-xr-xsetup.sh18
9 files changed, 500 insertions, 0 deletions
diff --git a/.env.dist b/.env.dist
new file mode 100644
index 0000000..90d0901
--- /dev/null
+++ b/.env.dist
@@ -0,0 +1,8 @@
+TZ=Europe/Moscow
+EMAIL=YOUR_EMAIL
+HOST=YOUR_DOMAIN
+PG_USER=docker
+PG_PASSWORD=CHANGE_PASSWORD
+REDIS_PASSWORD=CHANGE_PASSWORD
+TRANSMISSION_USER=root
+TRANSMISSION_PASSWORD=CHANGE_PASSWORD \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2eea525
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.env \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..866b339
--- /dev/null
+++ b/README.md
@@ -0,0 +1,55 @@
+# TinyNAS
+
+Дистрибутив софта на базе докера для быстрого развертования домашнего NAS.
+
+В дистрибутив входят:
+
+* Transmission - торрент клиент
+* miniDLNA - DLNA сервер для трансляции скачанных файлов на ТВ/другие устройства
+* NextCloud - персональное облако
+* VaultWarden - селфхостед менеджер паролей, свободная реализация Bitwarden
+
+Помимо этого, сконфигурированы Caddy, Postgres, Redis чтобы всю эту красоту поддерживать.
+
+## Перед установкой:
+
+Требования для установки:
+
+* Сервер доступный снаружи
+* Домен который смотрит на этот сервер (его нужно будет указать в первом шаге установки)
+* docker + docker-compose
+
+## Установка:
+
+1. Запустить на сервере `./setup.sh` для генерации файла настроек .env
+2. Запустить TinyNAS: `docker compose up -d`
+
+## Использование
+
+Здесь и далее будет использоваться `example.com` как домен указанный 1 шаге установки
+
+### Transmission
+
+Адрес: https://transmission.example.com/
+
+Логин: TRANSMISSION_USER из файла .env
+
+Пароль: TRANSMISSION_PASSWORD из файла .env
+
+### Nextcloud
+
+Адрес: https://nextcloud.example.com/
+
+Необходимо ввести новый логин и пароль для создания администратора. Нажать "Создать".
+
+После этого в какой-то момент будет ошибка таймаута браузера. Это *нормально*!
+
+Ничего не делаем, обновляем страницу раз в пару минут, пока окно создания администратора не сменится на окно входа.
+
+Почему так - не знаю. Но оно работает. Пуллреквесты приветствуются.
+
+### VaultWarden
+
+Адрес: https://vaultwarden.example.com/
+
+Тут нет особенностей. Оно просто работает. \ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..34a32f3
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,238 @@
+version: "3.0"
+
+volumes:
+ media:
+ transmission-config:
+ transmission-watch:
+ nextcloud-config:
+ nextcloud-data:
+ nextcloud-www:
+ caddy-config:
+ caddy-data:
+ vw-data:
+ postgres-data:
+ postgres-backups:
+
+networks:
+ inner:
+
+services:
+ minidlna:
+ build:
+ context: minidlna
+ dockerfile: Dockerfile
+ container_name: dlna
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ MINIDLNA_MEDIA_DIR: /media
+ MINIDLNA_FRIENDLY_NAME: tinyNAS
+ volumes:
+ - media:/media
+ healthcheck:
+ test:
+ [
+ "CMD",
+ "curl",
+ "--silent",
+ "--fail",
+ "127.0.0.1:8200",
+ "||",
+ "exit 1"
+ ]
+ interval: 10s
+ timeout: 10s
+ retries: 6
+ start_period: 10s
+ restart: unless-stopped
+ ports:
+ - 8200:8200
+
+ transmission:
+ image: lscr.io/linuxserver/transmission:latest
+ container_name: transmission
+ environment:
+ - PUID=1000
+ - PGID=1000
+ - TZ=${TZ}
+ - USER=${TRANSMISSION_USER}
+ - PASS=${TRANSMISSION_PASSWORD}
+ volumes:
+ - transmission-config:/config
+ - media:/downloads
+ - transmission-watch:/watch
+ ports:
+ - 51413:51413
+ - 51413:51413/udp
+ restart: unless-stopped
+ networks:
+ - inner
+
+ nextcloud:
+ image: nextcloud:stable-fpm-alpine
+ container_name: nextcloud
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ POSTGRES_DB: nextcloud
+ POSTGRES_USER: ${PG_USER}
+ POSTGRES_PASSWORD: ${PG_PASSWORD}
+ POSTGRES_HOST: postgres:5432
+ NEXTCLOUD_TRUSTED_DOMAINS: nextcloud.${HOST}
+ REDIS_HOST: redis
+ REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
+ volumes:
+ - nextcloud-config:/config:rw
+ - nextcloud-data:/var/data:rw
+ - nextcloud-www:/var/www/html:rw
+ restart: unless-stopped
+ networks:
+ - inner
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_started
+
+ nextcloud-cron:
+ image: nextcloud:stable-fpm-alpine
+ restart: always
+ container_name: nextcloud-cron
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ POSTGRES_DB: nextcloud
+ POSTGRES_USER: ${PG_USER}
+ POSTGRES_PASSWORD: ${PG_PASSWORD}
+ POSTGRES_HOST: postgres:5432
+ NEXTCLOUD_TRUSTED_DOMAINS: nextcloud.${HOST}
+ REDIS_HOST: redis
+ REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
+ volumes:
+ - nextcloud-config:/config:rw
+ - nextcloud-data:/data:rw
+ - nextcloud-www:/var/www/html:rw
+ entrypoint: /cron.sh
+ networks:
+ - inner
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_started
+
+ vaultwarden:
+ image: vaultwarden/server:latest
+ container_name: vaultwarden
+ restart: always
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ WEBSOCKET_ENABLED: "true"
+ DATABASE_URL: postgresql://${PG_USER}:${PG_PASSWORD}@postgres:5432/vaultwarden
+ volumes:
+ - vw-data:/data
+ networks:
+ - inner
+ depends_on:
+ postgres:
+ condition: service_healthy
+
+ gateway:
+ image: caddy:2
+ container_name: caddy
+ restart: always
+ ports:
+ - 80:80
+ - 443:443
+ volumes:
+ - ./etc/Caddyfile:/etc/caddy/Caddyfile:ro
+ - caddy-config:/config:rw
+ - caddy-data:/data:rw
+ - nextcloud-www:/var/www/nextcloud:rw
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ HOST: ${HOST}
+ EMAIL: ${EMAIL}
+ LOG_FILE: "/data/access.log"
+ networks:
+ - inner
+ depends_on:
+ - nextcloud
+ - vaultwarden
+ - transmission
+
+ postgres:
+ image: postgres:15.2-alpine3.17
+ restart: always
+ container_name: postgres
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ PGUSER: ${PG_USER}
+ POSTGRES_USER: ${PG_USER}
+ POSTGRES_PASSWORD: ${PG_PASSWORD}
+ DB_NAME: nextcloud,vaultwarden
+ LANG: ru_RU.utf8
+ volumes:
+ - "postgres-data:/var/lib/postgresql/data"
+ - "./etc/init.sql:/docker-entrypoint-initdb.d/init.sql"
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d vaultwarden -U docker"]
+ interval: 20s
+ timeout: 10s
+ retries: 10
+ networks:
+ - inner
+
+ backups:
+ image: postgres:15.2-alpine3.17
+ container_name: postgres_backup
+ # Run nextcloud-restore-application-data.sh to restore application data if needed.
+ # Run nextcloud-restore-database.sh to restore database if needed.
+ command: sh -c 'sleep 30m
+ && while true; do
+ PGPASSWORD="$$(echo $$POSTGRES_PASSWORD)"
+ pg_dump
+ -h postgres
+ -p 5432
+ -d nextcloud
+ -U docker | gzip > /srv/nextcloud-postgres/backups/nextcloud-postgres-backup-$$(date "+%Y-%m-%d_%H-%M").gz
+ && tar -zcpf /srv/nextcloud-application-data/backups/nextcloud-application-data-backup-$$(date "+%Y-%m-%d_%H-%M").tar.gz /var/www/html
+ && find /srv/nextcloud-postgres/backups -type f -mtime +7 | xargs rm -f
+ && find /srv/nextcloud-application-data/backups -type f -mtime +7 | xargs rm -f;
+ sleep 24h; done'
+ environment:
+ PUID: 1000
+ PGID: 1000
+ TZ: ${TZ}
+ PGUSER: ${PG_USER}
+ POSTGRES_USER: ${PG_USER}
+ POSTGRES_PASSWORD: ${PG_PASSWORD}
+ DB_NAME: nextcloud,vaultwarden
+ LANG: ru_RU.utf8
+ volumes:
+ - "postgres-data:/var/lib/postgresql/data"
+ # Database backups location
+ - "postgres-backups:/srv/nextcloud-postgres/backups"
+ restart: unless-stopped
+ depends_on:
+ postgres:
+ condition: service_healthy
+
+ redis:
+ container_name: redis
+ image: redis:alpine3.17
+ restart: always
+ mem_limit: 2048m
+ mem_reservation: 512m
+ command: redis-server --requirepass $REDIS_PASSWORD
+ networks:
+ - inner \ No newline at end of file
diff --git a/etc/Caddyfile b/etc/Caddyfile
new file mode 100644
index 0000000..0239f72
--- /dev/null
+++ b/etc/Caddyfile
@@ -0,0 +1,101 @@
+{
+ servers :443 {
+ timeouts {
+ idle 600s
+ read_body 600s
+ read_header 600s
+ write 600s
+ }
+ max_header_size 100MB
+ }
+ servers {
+ timeouts {
+ idle 600s
+ read_body 600s
+ read_header 600s
+ write 600s
+ }
+ max_header_size 20MB
+ }
+}
+
+nextcloud.{$HOST} {
+ log {
+ level INFO
+ output file {$LOG_FILE} {
+ roll_size 10MB
+ roll_keep 10
+ }
+ }
+
+ tls {$EMAIL}
+
+ encode gzip
+
+ header {
+ # enable HSTS
+ # Strict-Transport-Security max-age=31536000;
+ }
+
+ file_server
+ root * /var/www/nextcloud
+
+ @forbidden {
+ path /.htaccess
+ path /data/*
+ path /config/*
+ path /db_structure
+ path /.xml
+ path /README
+ path /3rdparty/*
+ path /lib/*
+ path /templates/*
+ path /occ
+ path /console.php
+ }
+ respond @forbidden 404
+ php_fastcgi nextcloud:9000 {
+ root /var/www/html
+ env front_controller_active true
+ dial_timeout 600s
+ read_timeout 600s
+ write_timeout 600s
+ }
+}
+
+vaultwarden.{$HOST} {
+ log {
+ level INFO
+ output file {$LOG_FILE} {
+ roll_size 10MB
+ roll_keep 10
+ }
+ }
+
+ tls {$EMAIL}
+
+ encode gzip
+
+ reverse_proxy /notifications/hub vaultwarden:3012
+ reverse_proxy vaultwarden:80 {
+ header_up X-Real-IP {remote_host}
+ }
+}
+
+transmission.{$HOST} {
+ log {
+ level INFO
+ output file {$LOG_FILE} {
+ roll_size 10MB
+ roll_keep 10
+ }
+ }
+
+ tls {$EMAIL}
+
+ encode gzip
+
+ reverse_proxy transmission:9091 {
+ header_up X-Real-IP {remote_host}
+ }
+}
diff --git a/etc/init.sql b/etc/init.sql
new file mode 100644
index 0000000..e42c6bd
--- /dev/null
+++ b/etc/init.sql
@@ -0,0 +1,4 @@
+CREATE DATABASE nextcloud;
+GRANT ALL PRIVILEGES ON DATABASE nextcloud TO docker;
+CREATE DATABASE vaultwarden;
+GRANT ALL PRIVILEGES ON DATABASE vaultwarden TO docker; \ No newline at end of file
diff --git a/minidlna/Dockerfile b/minidlna/Dockerfile
new file mode 100644
index 0000000..d8d4332
--- /dev/null
+++ b/minidlna/Dockerfile
@@ -0,0 +1,13 @@
+FROM alpine:3.17.2
+LABEL maintainer "Alexander Kiryukhin i@neonxp.dev"
+
+# Install
+RUN apk --no-cache add bash curl minidlna tini shadow su-exec alpine-conf inotify-tools
+
+# Entrypoint
+COPY entrypoint.sh /
+RUN chmod +x /entrypoint.sh
+
+EXPOSE 8200
+
+ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"] \ No newline at end of file
diff --git a/minidlna/entrypoint.sh b/minidlna/entrypoint.sh
new file mode 100755
index 0000000..5b77916
--- /dev/null
+++ b/minidlna/entrypoint.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+# Bash strict mode
+set -euo pipefail
+IFS=$'\n\t'
+
+# DEBUG
+[ -z "${DEBUG:-}" ] || set -x
+
+# VARs
+export TZ="${TZ:-}"
+export PUID="${PUID:-100}"
+export PGID="${PGID:-101}"
+export PIDFILE='/minidlna/minidlna.pid'
+export FORCE_SCAN="${FORCE_SCAN:-false}"
+export FORCE_REBUILD="${FORCE_REBUILD:-false}"
+
+# Remove old pid if it exists
+[ -f "$PIDFILE" ] && rm -f "$PIDFILE"
+
+echo '=== Set user and group identifier'
+groupmod --non-unique --gid "$PGID" minidlna
+usermod --non-unique --uid "$PUID" minidlna
+
+if [[ -n "$TZ" ]]; then
+ echo '=== Set timezone'
+ setup-timezone -z "$TZ"
+fi
+
+echo '=== Set standard configuration'
+export MINIDLNA_DB_DIR="${MINIDLNA_DB_DIR:-/minidlna/cache}"
+export MINIDLNA_LOG_DIR="${MINIDLNA_LOG_DIR:-/minidlna}"
+export MINIDLNA_INOTIFY="${MINIDLNA_INOTIFY:-yes}"
+
+echo '=== Set configuration from environment variables'
+: > /etc/minidlna.conf
+for VAR in $(env); do
+ if [[ "$VAR" =~ ^MINIDLNA_ ]]; then
+ if [[ "$VAR" =~ ^MINIDLNA_MEDIA_DIR ]]; then
+ minidlna_name='media_dir'
+ else
+ minidlna_name=$(echo "$VAR" | sed -r "s/MINIDLNA_(.*)=.*/\\1/g" | tr '[:upper:]' '[:lower:]')
+ fi
+ minidlna_value=$(echo "$VAR" | sed -r "s/.*=(.*)/\\1/g")
+ echo "${minidlna_name}=${minidlna_value}" >> /etc/minidlna.conf
+ fi
+done
+
+echo '=== Set permissions'
+mkdir -p /minidlna/ "${MINIDLNA_DB_DIR}" "${MINIDLNA_LOG_DIR}"
+chown -R "${PUID}:${PGID}" /minidlna/ "${MINIDLNA_DB_DIR}" "${MINIDLNA_LOG_DIR}"
+
+echo '=== Generate scan/rebuild flags'
+if [[ "$FORCE_SCAN" == true ]]; then
+ set -- -r "$@"
+fi
+if [[ "$FORCE_REBUILD" == true ]]; then
+ set -- -R "$@"
+fi
+
+echo '=== Start daemon'
+exec su-exec minidlna /usr/sbin/minidlnad -P "$PIDFILE" -S "$@" \ No newline at end of file
diff --git a/setup.sh b/setup.sh
new file mode 100755
index 0000000..63825d9
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+read -p "Ваш e-mail: " EMAIL
+read -p "Базовый домен, для которого будут созданы поддомены с сервисами: " HOST
+
+PG_PASSWORD=`tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo ''`
+REDIS_PASSWORD=`tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo ''`
+TRANSMISSION_PASSWORD=`tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo ''`
+
+echo "TZ=Europe/Moscow
+EMAIL=${EMAIL}
+HOST=${HOST}
+PG_USER=docker
+PG_PASSWORD=${PG_PASSWORD}
+REDIS_PASSWORD=${REDIS_PASSWORD}
+TRANSMISSION_USER=root
+TRANSMISSION_PASSWORD=${TRANSMISSION_PASSWORD}" > .env
+echo "Конфиг записан в файл .env" \ No newline at end of file