This commit is contained in:
NeonXP 2023-02-19 00:27:14 +03:00
commit 2639194501
9 changed files with 500 additions and 0 deletions

8
.env.dist Normal file
View File

@ -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

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

55
README.md Normal file
View File

@ -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/
Тут нет особенностей. Оно просто работает.

238
docker-compose.yml Normal file
View File

@ -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

101
etc/Caddyfile Normal file
View File

@ -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}
}
}

4
etc/init.sql Normal file
View File

@ -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;

13
minidlna/Dockerfile Normal file
View File

@ -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"]

62
minidlna/entrypoint.sh Executable file
View File

@ -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 "$@"

18
setup.sh Executable file
View File

@ -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"