├── .gitignore ├── Dockerfile ├── README.md ├── cloud ├── README.md ├── rclone.service ├── unionfs.service ├── upload.service └── upload.timer ├── config.default ├── container-root ├── init └── usr │ └── local │ └── etc │ └── haproxy │ └── haproxy.cfg ├── docker-compose.cloud.yml └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | /config 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM haproxy:1.8-alpine 2 | 3 | COPY container-root/ / 4 | 5 | CMD /init 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Seedbox 2 | This project helps you run a seedbox and media server in Docker. 3 | 4 | ## Included Applications 5 | | Application | Web Interface | 6 | -----------------------|-------------------------| 7 | | Plex | plex.yourdomain.com | 8 | | rtorrent + ruTorrent | rtorrent.yourdomain.com | 9 | | Sonarr | sonarr.yourdomain.com | 10 | | Radarr | radarr.yourdomain.com | 11 | | Jackett | jackett.yourdomain.com | 12 | | OpenVPN | ----------------------- | 13 | 14 | ## Dependencies 15 | - [Docker](https://github.com/docker/docker) >= 1.13.0 16 | - [Docker Compose](https://github.com/docker/compose) >= 1.10.0 17 | 18 | ## Quickstart 19 | 20 | ### Config 21 | Copy `config.default` to `config` and edit the variables inside. 22 | 23 | ### Starting 24 | ```sh 25 | docker-compose pull 26 | docker-compose up -d 27 | ``` 28 | ### Where is my data? 29 | Config files are stored in the `seedbox_config` volume and 30 | other data is stored in the `seedbox_data` volume. You can 31 | change this by editing the `docker-compose.yml` file. 32 | 33 | ## Plex 34 | If you own PlexPass, you can get the docker image to auto-update to the latest 35 | PlexPass version when the container starts up. Simply set the `PLEX_TOKEN` 36 | variable in the config file. 37 | 38 | ## OpenVPN 39 | Go [here](https://github.com/kelvin-containers/openvpn) for more information 40 | on how to configure OpenVPN and generate more certificates. 41 | -------------------------------------------------------------------------------- /cloud/README.md: -------------------------------------------------------------------------------- 1 | # Cloud Storage (with Google Drive) 2 | 3 | Set up rclone based on the config below. 4 | Basically, the structure is Google Drive => cache => encryption. 5 | 6 | After setting up rclone, copy the systemd unit files over to `/etc/systemd/system` and enable/start them. 7 | 8 | ``` 9 | [gcache] 10 | type = cache 11 | remote = gdrive: 12 | plex_url = 13 | plex_username = 14 | plex_password = 15 | chunk_size = 10M 16 | info_age = 168h 17 | chunk_total_size = 18 | 19 | [gcrypt] 20 | type = crypt 21 | remote = gcache:encrypted 22 | filename_encryption = standard 23 | directory_name_encryption = true 24 | password = 25 | password2 = 26 | 27 | [gdrive] 28 | type = drive 29 | client_id = 30 | client_secret = 31 | scope = drive 32 | root_folder_id = 33 | service_account_file = 34 | token = 35 | team_drive = 36 | ``` 37 | 38 | ## Directory Structure 39 | 1. Union(rclone mount, `/data`) => `/mnt/cloud` 40 | 2. `/mnt/cloud` => `/cloud` in Docker 41 | 3. `/data/.downloads` => `/downloads` in Docker (rtorrent container only) 42 | 43 | The downloads mount (3) is mounted as a workaround since rtorrent won't directly 44 | download to the UnionFS mount (2). To make sure Sonarr/Radarr imports everything 45 | correctly and works with hard links, make sure to set downloads directory to 46 | `/downloads` and create a path mapping with the values below: 47 | 48 | | Host | Remote Path | Local Path | 49 | -----------|-------------|--------------------| 50 | | rtorrent | /downloads/ | /cloud/.downloads/ | 51 | -------------------------------------------------------------------------------- /cloud/rclone.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Rclone mount (gdrive => gcache => gcrypt) 3 | Documentation=http://rclone.org/docs/ 4 | After=network-online.target 5 | Requires=network-online.target 6 | AssertPathIsDirectory=/mnt/.gcrypt 7 | 8 | [Service] 9 | Type=notify 10 | User=root 11 | Group=root 12 | ExecStart=/usr/bin/rclone mount --allow-other --cache-rps 5 --vfs-cache-mode writes gcrypt: /mnt/.gcrypt 13 | ExecStop=/bin/fusermount -uz /mnt/.gcrypt 14 | Restart=always 15 | RestartSec=5 16 | StartLimitInterval=60s 17 | StartLimitBurst=5 18 | 19 | [Install] 20 | WantedBy=default.target 21 | -------------------------------------------------------------------------------- /cloud/unionfs.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=UnionFS mount 3 | After=rclone.service 4 | Requires=rclone.service 5 | AssertPathIsDirectory=/mnt/cloud 6 | 7 | [Service] 8 | Type=forking 9 | User=root 10 | Group=root 11 | ExecStart=/usr/bin/unionfs -o max_files=65536,cow,allow_other,direct_io,sync_read /data=RW:/mnt/.gcrypt=RW /mnt/cloud 12 | ExecStop=/usr/bin/fusermount -uz /mnt/cloud 13 | Restart=always 14 | RestartSec=5 15 | StartLimitInterval=60s 16 | StartLimitBurst=5 17 | 18 | [Install] 19 | WantedBy=default.target 20 | RequiredBy=docker.service 21 | -------------------------------------------------------------------------------- /cloud/upload.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Upload from local storage to cloud mount 3 | 4 | [Service] 5 | Type=oneshot 6 | User=root 7 | Group=root 8 | ExecStart=/usr/bin/rclone move /data/ /mnt/.gcrypt/ --delete-after --min-age 5m --exclude /.downloads/ 9 | -------------------------------------------------------------------------------- /cloud/upload.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Upload from local storage to cloud mount once every day 3 | 4 | [Timer] 5 | OnCalendar=*-*-* 05:00:00 6 | 7 | [Install] 8 | WantedBy=timers.target 9 | -------------------------------------------------------------------------------- /config.default: -------------------------------------------------------------------------------- 1 | # Web interface settings 2 | USERNAME=user 3 | PASSWORD=pass 4 | 5 | # Set timezone 6 | TZ=US/Eastern 7 | 8 | # For Plex Pass download 9 | PLEX_TOKEN= 10 | -------------------------------------------------------------------------------- /container-root/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "userlist users 4 | user $USERNAME insecure-password $PASSWORD 5 | " > /usr/local/etc/haproxy/auth.cfg 6 | 7 | exec haproxy -W -db -f /usr/local/etc/haproxy/auth.cfg -f /usr/local/etc/haproxy/haproxy.cfg 8 | -------------------------------------------------------------------------------- /container-root/usr/local/etc/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | # vim:ft=haproxy 2 | 3 | global 4 | maxconn 1024 5 | 6 | defaults 7 | mode http 8 | timeout connect 5000ms 9 | timeout client 50000ms 10 | timeout server 50000ms 11 | 12 | frontend http-in 13 | bind *:80 alpn h2,http/1.1 14 | 15 | acl auth_uat http_auth(users) uat 16 | 17 | acl host_rtorrent hdr_reg(host) -i ^rtorrent\.[^\.]+ 18 | acl host_plex hdr_reg(host) -i ^plex\.[^\.]+ 19 | acl host_sonarr hdr_reg(host) -i ^sonarr\.[^\.]+ 20 | acl host_radarr hdr_reg(host) -i ^radarr\.[^\.]+ 21 | acl host_jackett hdr_reg(host) -i ^jackett\.[^\.]+ 22 | 23 | http-request auth realm uat if !auth_uat !host_plex 24 | 25 | use_backend rtorrent if host_rtorrent 26 | use_backend plex if host_plex 27 | use_backend sonarr if host_sonarr 28 | use_backend radarr if host_radarr 29 | use_backend jackett if host_jackett 30 | 31 | backend rtorrent 32 | server rtorrent rtorrent:80 33 | 34 | backend plex 35 | server plex plex:32400 36 | 37 | backend sonarr 38 | server sonarr media-manager:8989 39 | 40 | backend radarr 41 | server radarr media-manager:7878 42 | 43 | backend jackett 44 | server jackett media-manager:9117 45 | -------------------------------------------------------------------------------- /docker-compose.cloud.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | rtorrent: 6 | volumes: 7 | - /mnt/cloud:/cloud 8 | - /data/.downloads:/downloads 9 | 10 | plex: 11 | volumes: 12 | - /mnt/cloud:/cloud 13 | 14 | media-manager: 15 | volumes: 16 | - /mnt/cloud:/cloud 17 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | networks: 4 | main: 5 | 6 | volumes: 7 | config: 8 | driver: local 9 | data: 10 | driver: local 11 | 12 | services: 13 | 14 | proxy: 15 | image: kelvinchen/seedbox:latest 16 | build: . 17 | restart: always 18 | networks: 19 | - main 20 | ports: 21 | - "80:80" 22 | - "443:443" 23 | volumes: 24 | - config:/config 25 | env_file: 26 | - config 27 | 28 | rtorrent: 29 | image: kelvinchen/rtorrent:latest 30 | restart: always 31 | networks: 32 | - main 33 | ports: 34 | - "49161:49161" 35 | - "49161:49161/udp" 36 | - "6881:6881/udp" 37 | volumes: 38 | - config:/config 39 | - data:/data 40 | env_file: 41 | - config 42 | 43 | plex: 44 | image: kelvinchen/plex:latest 45 | restart: always 46 | networks: 47 | - main 48 | ports: 49 | - "32400:32400" 50 | volumes: 51 | - config:/config 52 | - data:/data 53 | env_file: 54 | - config 55 | devices: 56 | - /dev/dri:/dev/dri 57 | privileged: true 58 | 59 | media-manager: 60 | image: kelvinchen/media-manager:latest 61 | restart: always 62 | networks: 63 | - main 64 | volumes: 65 | - config:/config 66 | - data:/data 67 | env_file: 68 | - config 69 | 70 | openvpn: 71 | image: kelvinchen/openvpn:latest 72 | restart: always 73 | networks: 74 | - main 75 | ports: 76 | - "1194:1194/udp" 77 | volumes: 78 | - config:/config 79 | - data:/data 80 | env_file: 81 | - config 82 | cap_add: 83 | - NET_ADMIN 84 | sysctls: 85 | - net.ipv6.conf.all.disable_ipv6=0 86 | - net.ipv6.conf.default.forwarding=1 87 | - net.ipv6.conf.all.forwarding=1 88 | --------------------------------------------------------------------------------