diff --git a/.env.app.example b/.env.app.example new file mode 100644 index 0000000..a2a7122 --- /dev/null +++ b/.env.app.example @@ -0,0 +1,15 @@ +IP_INFO_URL=https://ipinfo.io/json +TRANSMISSION_HOST=localhost +TRANSMISSION_PORT=9091 +DOCKER_TRANSMISSION_CWD=/path/to/transmission/docker-compose/yaml/config +DOCKER_TRANSMISSION_SERVICE=transmission +DOCKER_TRANSMISSION_SERVICE_NAME=transmission +DOCKER_GLUETUN_CWD=/path/to/gluetun/docker-compose/yaml/config +DOCKER_GLUETUN_SERVICE=gluetun +DOCKER_GLUETUN_SERVICE_NAME=gluetun +ALLOWED_INTERFACES=tun0 +DISALLOWED_COUNTRIES=your_country_code_e_g_LV +DISALLOWED_INTERNAL_IPS=your_internal_ip_e_g_192.168 +DISALLOWED_EXT_IPS=your_external_ip +DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your_webhook_url +UPDATE_INTERVAL_SECONDS=300 diff --git a/.env.example b/.env.example index 2e0675a..c059893 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,4 @@ -IP_INFO_URL=https://ipinfo.io/json -TRANSMISSION_HOST=localhost -TRANSMISSION_PORT=9091 -DOCKER_TRANSMISSION_CWD=/path/to/transmission/docker-compose/yaml/config -DOCKER_TRANSMISSION_SERVICE=transmission -DOCKER_TRANSMISSION_SERVICE_NAME=transmission -ALLOWED_INTERFACES=tun0 -DISALLOWED_COUNTRIES=your_country_code_e_g_LV -DISALLOWED_INTERNAL_IPS=your_internal_ip_e_g_192.168 -DISALLOWED_EXT_IPS=your_external_ip -DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your_webhook_url -UPDATE_INTERVAL_SECONDS=300 +#this is env file for docker-compose file (not for the apps) +CONFIG_DIR=/mnt/hdd/transmission-config +DOWNLOAD_DIR1=/mnt/hdd/downloads +DOWNLOAD_DIR2=/mnt/hdd2/downloads diff --git a/.env.gluetun.example b/.env.gluetun.example new file mode 100644 index 0000000..3742f43 --- /dev/null +++ b/.env.gluetun.example @@ -0,0 +1,4 @@ +VPN_SERVICE_PROVIDER=privatevpn +OPENVPN_USER=user +OPENVPN_PASSWORD=passw +SERVER_COUNTRIES=Sweden,Poland diff --git a/.env.transmission.example b/.env.transmission.example new file mode 100644 index 0000000..cd29d84 --- /dev/null +++ b/.env.transmission.example @@ -0,0 +1,9 @@ +PUID=1000 +PGID=1000 +TZ=Europe/Warsaw +TRANSMISSION_WEB_HOME= #optional +USER= #optional +PASS= #optional +WHITELIST= #optional +PEERPORT= #optional +HOST_WHITELIST= #optional diff --git a/.gitignore b/.gitignore index 4c96c08..06a6d27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules -.env +.env** +!.env**example .idea diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1a25f88 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +services: + gluetun: + image: qmcgaw/gluetun + container_name: gluetun + cap_add: + - NET_ADMIN + env_file: + - .env.gluetun + ports: + - "9091:9091/tcp" + - "8000:8000/tcp" + + transmission: + image: lscr.io/linuxserver/transmission:latest + container_name: transmission + env_file: + - ./.env.transmission + volumes: + - ${CONFIG_DIR}:/config + - ${DOWNLOAD_DIR1}:${DOWNLOAD_DIR1} + - ${DOWNLOAD_DIR2}:${DOWNLOAD_DIR2} + restart: unless-stopped + network_mode: "service:gluetun" diff --git a/src/docker.ts b/src/docker.ts index 56303c8..bb72150 100644 --- a/src/docker.ts +++ b/src/docker.ts @@ -60,4 +60,11 @@ export class DockerContainer { ip: dataRaw[6], } } + + async setOpenFirewallPort(port: number) { + const {exitCode: exit0} = await this.exec(`iptables -A INPUT -i tun0 -p tcp --dport ${port} -j ACCEPT`); + const {exitCode: exit1} = await this.exec(`iptables -A INPUT -i tun0 -p udp --dport ${port} -j ACCEPT`); + + return exit0 === 0 && exit1 === 0; + } } diff --git a/src/set-port-flow.ts b/src/set-port-flow.ts index 9760b82..8f28660 100644 --- a/src/set-port-flow.ts +++ b/src/set-port-flow.ts @@ -20,8 +20,14 @@ export async function setPortFlow() { settings.dockerTransmission.cwd, settings.dockerTransmission.serviceName ); + const gluetunContainer = new DockerContainer( + settings.dockerGluetun.service, + settings.dockerGluetun.cwd, + settings.dockerGluetun.serviceName + ); + try { - await doSetPortFlow(transmissionClient, transmissionContainer); + await doSetPortFlow(transmissionClient, transmissionContainer, gluetunContainer); } catch (e) { console.error('Error in set port flow', e); await downTransmission(transmissionContainer, `Shutting down: error in set port flow.`); @@ -29,7 +35,7 @@ export async function setPortFlow() { await dailyCheckIn(); } -async function doSetPortFlow(transmissionClient: Transmission, transmissionContainer: DockerContainer) { +async function doSetPortFlow(transmissionClient: Transmission, transmissionContainer: DockerContainer, gluetunContainer: DockerContainer) { console.log('Starting set port flow'); const containerState = await transmissionContainer.getState(); @@ -102,6 +108,14 @@ async function doSetPortFlow(transmissionClient: Transmission, transmissionConta } console.log(`Setting port to ${newPort}`); + const resultOK = await gluetunContainer.setOpenFirewallPort(newPort); + if (!resultOK) { + return await downTransmission( + transmissionContainer, + `Shutting down: could not open new port in gluetun firewall`, + ); + } + console.log(`Port in gluetun firewall opened successfully`); await transmissionClient.setPort(newPort); const numPortsChanged = kvDataStorage.get('numPortsChanged') || 0; diff --git a/src/settings.ts b/src/settings.ts index 8e1669c..200469e 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,5 +1,5 @@ import dotenv from 'dotenv'; -dotenv.config(); +dotenv.config({ path: '.env.app'}); export const settings = { ipInfoCommand: `curl ${process.env.IP_INFO_URL ?? 'https://ipinfo.io'}`, @@ -13,6 +13,11 @@ export const settings = { service: process.env.DOCKER_TRANSMISSION_SERVICE ?? 'transmission', serviceName: process.env.DOCKER_TRANSMISSION_SERVICE_NAME ?? process.env.DOCKER_TRANSMISSION_SERVICE, }, + dockerGluetun: { + cwd: process.env.DOCKER_GLUETUN_CWD ?? __dirname, + service: process.env.DOCKER_GLUETUN_SERVICE ?? 'gluetun', + serviceName: process.env.DOCKER_GLUETUN_SERVICE_NAME ?? process.env.DOCKER_GLUETUN_SERVICE, + }, allowedInterfaces: process.env.ALLOWED_INTERFACES?.split(',') ?? [], disallowedCountries: process.env.DISALLOWED_COUNTRIES?.split(',') ?? [], disallowedIntIps: process.env.DISALLOWED_INTERNAL_IPS?.split(',') ?? [],