migrate
This commit is contained in:
@@ -0,0 +1,431 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Media
|
||||
---
|
||||
Directory Structure
|
||||
cd docker
|
||||
mkdir -p ~/arr-stack/{config/{gluetun,qbittorrent,prowlarr,radarr,sonarr},data/{torrents,media/{movies,tv}}}
|
||||
cd ~/arr-stack
|
||||
touch docker-compose.yml .env
|
||||
|
||||
|
||||
```
|
||||
# Tom Spark's ARR Stack — Automated Media Server
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# Usage:
|
||||
# 1. Copy .env.example to .env and fill in your VPN credentials
|
||||
# 2. Run: bash setup-folders.sh
|
||||
# 3. Run: docker compose up -d
|
||||
#
|
||||
# All VPN-protected services (qBittorrent, Prowlarr, FlareSolverr) run
|
||||
# through Gluetun. If the VPN drops, traffic stops. Zero leaks.
|
||||
#
|
||||
# Radarr, Sonarr, Lidarr, Bazarr, Jellyfin, and Seerr do NOT run through
|
||||
# the VPN — they need direct network access for speed and local connectivity.
|
||||
|
||||
networks:
|
||||
arrnetwork:
|
||||
name: arrnetwork
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.39.0.0/24
|
||||
|
||||
services:
|
||||
|
||||
# ============================================================
|
||||
# GLUETUN — VPN Container (kill switch + tunnel)
|
||||
# All VPN-protected services route through this container.
|
||||
# Ports for those services are mapped HERE, not on the services themselves.
|
||||
# Docs: https://github.com/qdm12/gluetun-wiki
|
||||
# ============================================================
|
||||
gluetun:
|
||||
image: qmcgaw/gluetun:latest
|
||||
container_name: gluetun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_GLUETUN}
|
||||
ports:
|
||||
- 8000:8000 # Gluetun Control Server
|
||||
- 8080:8080 # qBittorrent WebUI
|
||||
- 6881:6881 # qBittorrent torrenting port
|
||||
- 6881:6881/udp
|
||||
- 9696:9696 # Prowlarr
|
||||
- 8191:8191 # FlareSolverr
|
||||
volumes:
|
||||
- ./gluetun:/gluetun
|
||||
environment:
|
||||
- VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER}
|
||||
- VPN_TYPE=${VPN_TYPE}
|
||||
# --- WireGuard credentials (most providers) ---
|
||||
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
|
||||
- WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES}
|
||||
# - WIREGUARD_PUBLIC_KEY=${WIREGUARD_PUBLIC_KEY}
|
||||
- WIREGUARD_PRESHARED_KEY=${WIREGUARD_PRESHARED_KEY}
|
||||
# --- OpenVPN credentials (if using OpenVPN instead) ---
|
||||
# - OPENVPN_USER=${OPENVPN_USER}
|
||||
# - OPENVPN_PASSWORD=${OPENVPN_PASSWORD}
|
||||
# --- Server selection ---
|
||||
- SERVER_COUNTRIES=${SERVER_COUNTRIES}
|
||||
# --- Port forwarding (ProtonVPN, AirVPN, PIA) ---
|
||||
# - VPN_PORT_FORWARDING=${VPN_PORT_FORWARDING}
|
||||
- FIREWALL_VPN_INPUT_PORTS=${FIREWALL_VPN_INPUT_PORTS}
|
||||
# --- General ---
|
||||
- TZ=${TZ}
|
||||
- BLOCK_MALICIOUS=off
|
||||
- HTTP_CONTROL_SERVER_ADDRESS=:8000
|
||||
- HTTP_CONTROL_SERVER_LOG=on
|
||||
- HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE={"auth":"none"}
|
||||
healthcheck:
|
||||
test: wget -qO /dev/null http://127.0.0.1:9999 || exit 1
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# QBITTORRENT — Torrent Client (runs through Gluetun VPN)
|
||||
# ALL traffic goes through the VPN tunnel. No direct internet.
|
||||
# ============================================================
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
labels:
|
||||
- deunhealth.restart.on.unhealthy=true
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
- WEBUI_PORT=8080
|
||||
- TORRENTING_PORT=${FIREWALL_VPN_INPUT_PORTS}
|
||||
volumes:
|
||||
- ./qbittorrent:/config
|
||||
- /data:/data
|
||||
healthcheck:
|
||||
test: wget -q --spider http://localhost:8080 || exit 1
|
||||
interval: 60s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# DEUNHEALTH — Auto-restarts unhealthy containers
|
||||
# If qBittorrent loses VPN connection, this restarts it automatically.
|
||||
# ============================================================
|
||||
deunhealth:
|
||||
image: qmcgaw/deunhealth
|
||||
container_name: deunhealth
|
||||
network_mode: none
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- HEALTH_SERVER_ADDRESS=127.0.0.1:9999
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
restart: always
|
||||
# ============================================================
|
||||
# PROWLARR — Indexer Manager (runs through Gluetun VPN)
|
||||
# Manages torrent/usenet indexers. Syncs to Radarr/Sonarr/Lidarr.
|
||||
# ============================================================
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./prowlarr:/config
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# FLARESOLVERR — Cloudflare Bypass (runs through Gluetun VPN)
|
||||
# Some indexers use Cloudflare protection. This gets around it.
|
||||
# ============================================================
|
||||
flaresolverr:
|
||||
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||||
container_name: flaresolverr
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- TZ=${TZ}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# RADARR — Movie Manager (NOT behind VPN)
|
||||
# Searches via Prowlarr, sends downloads to qBittorrent,
|
||||
# renames and hard-links completed files to media folder.
|
||||
# ============================================================
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./radarr:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 7878:7878
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_RADARR}
|
||||
restart: unless-stopped
|
||||
# ============================================================
|
||||
# SONARR — TV Show Manager (NOT behind VPN)
|
||||
# Same pattern as Radarr but for TV series.
|
||||
# ============================================================
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./sonarr:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 8989:8989
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_SONARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# LIDARR — Music Manager (NOT behind VPN)
|
||||
# Optional. Comment out if you don't need music automation.
|
||||
# ============================================================
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./lidarr:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 8686:8686
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_LIDARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# BAZARR — Subtitle Manager (NOT behind VPN)
|
||||
# Automatically downloads subtitles for movies and TV shows.
|
||||
# ============================================================
|
||||
bazarr:
|
||||
image: lscr.io/linuxserver/bazarr:latest
|
||||
container_name: bazarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./bazarr:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 6767:6767
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_BAZARR}
|
||||
restart: unless-stopped
|
||||
# ============================================================
|
||||
# JELLYFIN — Media Server (NOT behind VPN)
|
||||
# Your personal streaming service. Plays movies, TV, music.
|
||||
# Needs full bandwidth — never put this behind the VPN.
|
||||
# ============================================================
|
||||
jellyfin:
|
||||
image: lscr.io/linuxserver/jellyfin:latest
|
||||
container_name: jellyfin
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./jellyfin:/config
|
||||
- /data/media:/data/media
|
||||
ports:
|
||||
- 8096:8096
|
||||
# Uncomment the lines below to enable hardware transcoding (Intel Quick Sync / VAAPI).
|
||||
# Only works if your system has Intel/AMD integrated graphics (/dev/dri must exist).
|
||||
# If you get an error about /dev/dri not found, leave these commented out.
|
||||
# devices:
|
||||
# - /dev/dri:/dev/dri
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_JELLYFIN}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# SEERR — Request System (NOT behind VPN)
|
||||
# Netflix-like UI for requesting movies and TV shows.
|
||||
# Share this with family — they never need to touch Radarr.
|
||||
#
|
||||
# Seerr is the unified successor to Overseerr and Jellyseerr
|
||||
# (merged under seerr-team). Supports Plex, Jellyfin, and Emby.
|
||||
#
|
||||
# Config uses a NAMED Docker volume (not a bind mount). This is
|
||||
# required: Seerr runs as the `node` user (UID 1000) and a
|
||||
# bind-mounted host folder is created root-owned, causing a
|
||||
# permission-denied crash loop. On Windows/WSL, bind mounts also
|
||||
# corrupt the SQLite DB over SMB. Named volumes fix both cases
|
||||
# (matches upstream Seerr docs).
|
||||
#
|
||||
# Migrating from ./jellyseerr or ./seerr bind mount? See README
|
||||
# troubleshooting "Migrating Seerr config to a named volume".
|
||||
# ============================================================
|
||||
seerr:
|
||||
image: ghcr.io/seerr-team/seerr:v3.0.1
|
||||
init: true
|
||||
container_name: seerr
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- TZ=${TZ}
|
||||
- PORT=5055
|
||||
volumes:
|
||||
- seerr_config:/app/config
|
||||
ports:
|
||||
- 5055:5055
|
||||
healthcheck:
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/settings/public || exit 1
|
||||
start_period: 20s
|
||||
timeout: 3s
|
||||
interval: 15s
|
||||
retries: 3
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_SEERR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# AUDIO BookShelf — Server (NOT behind VPN)
|
||||
# Your personal streaming service. Plays all audiobooks.
|
||||
# Needs full bandwidth — never put this behind the VPN.
|
||||
# ============================================================
|
||||
audiobookshelf:
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
container_name: audiobookshelf
|
||||
ports:
|
||||
- 13378:80
|
||||
volumes:
|
||||
- /data/media/audiobookshelf/books:/audiobooks
|
||||
- /data/media/audiobookshelf/podcasts:/podcasts
|
||||
- /data/media/audiobookshelf/metadata:/metadata
|
||||
- ./audiobookshelf/config:/config
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_AUDIO}
|
||||
|
||||
# ============================================================
|
||||
# NAVIDROME — Music Media Server (NOT behind VPN)
|
||||
# Your personal streaming service. Plays music.
|
||||
# Needs full bandwidth — never put this behind the VPN.
|
||||
# ============================================================
|
||||
navidrome:
|
||||
image: deluan/navidrome:latest
|
||||
user: 1000:1000
|
||||
container_name: navidrome
|
||||
ports:
|
||||
- 4533:4533
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ND_SCANSCHEDULE: "1h"
|
||||
ND_LOGLEVEL: info
|
||||
ND_SESSIONTIMEOUT: "24h"
|
||||
volumes:
|
||||
- ./navi/data:/data
|
||||
- /data/media/music:/music:ro
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_NAVI}
|
||||
|
||||
volumes:
|
||||
seerr_config:
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2. Step-by-Step qBittorrent Configuration
|
||||
|
||||
Once your stack is running via `docker compose up -d`, navigate to your qBittorrent interface at `http://localhost:8118` or your server's IP address (e.g., `[http://192.168.1.50:8118](http://192.168.1.50:8118)`).
|
||||
|
||||
### Step 2a: Log In and Find Credentials
|
||||
|
||||
- Look at your container logs (`docker logs qbittorrent`) to locate the **temporary password** generated automatically by linuxserver/qbittorrent for security.
|
||||
|
||||
- Use `admin` as the username and paste that password.
|
||||
|
||||
- _Recommended:_ Instantly go to **Tools > Options > Web UI** to change the password to a permanent one.
|
||||
|
||||
|
||||
### Step 2b: Configure Connection & Port Forwarding
|
||||
|
||||
This ensures your traffic efficiently routes through AirVPN's system:
|
||||
|
||||
**1.Open Connection Settings:**Inside Web UI.
|
||||
|
||||
Go to **Tools** in the top navigation bar and select **Options**. In the sidebar menu that pops up, click on **Connection**.
|
||||
|
||||
**2.Set the Torrenting Port:**Match Gluetun mapping.
|
||||
|
||||
Locate **Port used for incoming connections** and type in exactly: `29261`.
|
||||
|
||||
**3.Disable UPnP / NAT-PMP:**Security step.
|
||||
|
||||
**Uncheck** the box next to _Use UPnP / NAT-PMP port forwarding from my router_. Your VPN handles port assignment, so your local router shouldn't intervene.
|
||||
|
||||
### Step 2c: Bind to the VPN Interface (The Hard Kill Switch)
|
||||
|
||||
Binding ensures that if Gluetun ever collapses, leaks, or drops connection, qBittorrent immediately stops downloading or seeding instead of trying to pass data via an unprotected network.
|
||||
|
||||
**1.Open Advanced Panel:**Scroll down sidebar.
|
||||
|
||||
While still in the Options menu, scroll down the left sidebar panel and select **Advanced**.
|
||||
|
||||
**2.Bind Network Interface:**Target VPN tunnel.
|
||||
|
||||
Look for **Network interface** near the top of the list. Change the dropdown menu from _Any interface_ to exactly **`tun0`**.
|
||||
|
||||
**3.Bind IP Address:**Optional but safer.
|
||||
|
||||
Look right underneath at the **Optional IP address to bind to** setting. Change it from _All addresses_ to **`All IPv4 addresses`**.
|
||||
|
||||
**4.Save and Restart:**Apply changes.
|
||||
|
||||
Click **Save / Apply** at the bottom right. Restart your container with `docker compose restart qbittorrent` to guarantee the network interfaces lock into place cleanly.
|
||||
@@ -0,0 +1,254 @@
|
||||
---
|
||||
title: Configuring Arr Stack
|
||||
source: https://mafyuh.com/posts/arr-stack-config-guide/
|
||||
author:
|
||||
- "[[Matt]]"
|
||||
published: 2024-02-24
|
||||
created: 2026-07-09
|
||||
description: This is blog post 2/2 on setting up a Arr stack using docker. This post will touch on configuring these services and what I have learned when using these services. I will be referring to TRaSH-Guides often in this post. It’s like the bible of the Arr’s so I would look there for more options, especially if your setup differs from mine.PrerequisitesAny Usenet Server Subscription (preferred)Any Usenet Indexer Subscription (preferred)Real-Debrid Subscription (if you like torrents being fast)VPN Subscription (Bare minimum needed to download torrents)ConfigurationProwlarrWe will first start with Prowlarr and Sabnzbd to get all of this out of the way, and it’s the part where you’re gonna spend some $
|
||||
tags:
|
||||
- clippings
|
||||
- Media
|
||||
---
|
||||
This is blog post 2/2 on setting up a Arr stack using docker. This post will touch on configuring these services and what I have learned when using these services. I will be referring to [TRaSH-Guides](https://trash-guides.info/) often in this post. It’s like the bible of the Arr’s so I would look there for more options, especially if your setup differs from mine.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Any Usenet Server Subscription (preferred)
|
||||
- Any Usenet Indexer Subscription (preferred)
|
||||
- Real-Debrid Subscription (if you like torrents being fast)
|
||||
- VPN Subscription (Bare minimum needed to download torrents)
|
||||
|
||||
## Configuration
|
||||
|
||||
## Prowlarr
|
||||
|
||||
We will first start with Prowlarr and Sabnzbd to get all of this out of the way, and it’s the part where you’re gonna spend some $
|
||||
|
||||
1st thing to do is load up your web browser and go to Prowlarr. In your URL bar put http://{IP-ADDRESS}:9696.
|
||||
|
||||
You should be prompted to create an account. It doesn’t matter much if you choose Basic or Forms for authentication.
|
||||
|
||||
This guide is just going to be using Usenet, as I recommend it over torrenting.
|
||||
|
||||
Prowlarr’s job is to search thru all the indexers and return those results over to Radarr/Sonarr.
|
||||
|
||||
### Indexers
|
||||
|
||||
You can find links to all the indexers out there on this Usenet [subreddit](https://www.reddit.com/r/usenet/wiki/indexers/). I will provide a screenshot of my Indexers list:
|
||||
|
||||

|
||||
|
||||
I would say the most downloaded stuff I have is from NZBgeek, followed by DrunkenSlug then NZBFinder. If I were to only be able to have 1 it would be NZBgeek for sure.
|
||||
|
||||
Sign up for whatever service you want, once you pay they should give you your API key, usually under profile on the indexer website. Take that API over to Prowlarr and you should be able to select your indexer from the list, paste in your API key and save. You can also click on the wrench icon next to the indexer and set your VIP expiration date, so Prowlarr reminds you to renew.
|
||||
|
||||
I paid for as lifetime altHUB account as well as yearly for Slug and Geek, A lot of the others that are under Interactive Search Sync Profile are free accounts that they limit the amount of API hits per day. You can tell Prowlarr this to by setting up Sync Profiles like I have so it doesn’t burn your API hits fast. [Link](https://trash-guides.info/Prowlarr/prowlarr-setup-limited-api/)
|
||||
|
||||
Thats pretty much it for indexers, now you just need a provider which is covered in the Sabnzbd portion.
|
||||
|
||||
### Usenet vs Torrenting
|
||||
|
||||
Usenet wins all day IMO. I started off with torrenting years ago and there would always be something I couldn’t find. Once I found usenet that problem went away and hasn’t returned. I still have a Real-Debrid subscription, however I am not planning on renewing when it runs up as I just don’t need torrents anymore for media. The only exception being PPV fights, which at least with the indexers I use, I cant find much on usenet. Usenet grabs about 95% of what I need. And I’m sure the other 5% would have still been found, but torrent won the algorithm battle. You also do not need to use a VPN when using Usenet as all big providers use HTTPS.
|
||||
|
||||
If you are new to Usenet, their [subreddit](https://www.reddit.com/r/usenet/wiki/index/) wiki will help you out. Unlike torrenting which is peer to peer and fully decentralized, usenet is more centralized and has many servers that host the content (Providers). There is a monthly fee for being able to access these servers. You also need an indexer in order to find NZB files, which is then sent to your provider for downloading. Indexers are much cheaper at usually a few bucks a year.
|
||||
|
||||
### Connecting Prowlarr to Radarr/Sonarr
|
||||
|
||||
For now skip to setting up Radarr and Sonarr, after setting up you will need their API keys which can be found under **Settings - General - API Key**.
|
||||
|
||||
In Prowlarr go to **Settings - Apps - Create an application** and click Radarr, filling in all api key and changing the host if needed. Do the same thing for Sonarr. This automatically syncs all your indexers into Radarr/Sonarr and if you want to add more indexers you just have to add it in Prowlarr and not 2 separate places.
|
||||
|
||||
## Sabnzbd
|
||||
|
||||
Sab is what connects to our Usenet providers and downloads the NZB files that Radarr/Sonarr gave to it.
|
||||
|
||||
First load up sab at http://{IP\_ADDRESS}:8080. One of the first things it has you do is enter you server details, which takes us into providers.
|
||||
|
||||
### Providers
|
||||
|
||||
These are the costliest part of the process, although for good reason. There are a bunch of providers out there, which all can be found [here](https://www.reddit.com/r/usenet/wiki/providers/).
|
||||
|
||||
I have used Newshosting, NewsDemon and UsenetNow. You only need 1 of these to download most stuff, but I prefer to have 2 as I have seen some servers don’t have a file that another one did. It’s rare but happens. As of the time of me writing this I am using UsenetNow for $6/month and Newsdemon $50 for 12 months using this [link](https://members.newsdemon.com/billinginfo.php?pricepointid=20230413) (Not referral just found a promo link on Reddit I saved)
|
||||
|
||||
Once you select your provider and pay, they should email you your login credentials that you just put into Sab. Remember to set the connections to whatever your provider allows to maximize download speeds.
|
||||
|
||||
### Folders
|
||||
|
||||
All we really need to do to configure Sab is to set the Temp and Completed Download folders. For Temporary:
|
||||
|
||||
```
|
||||
/data/usenet/incomplete
|
||||
```
|
||||
|
||||
and for complete:
|
||||
|
||||
```
|
||||
/data/usenet/complete
|
||||
```
|
||||
|
||||
Make sure you save changes.
|
||||
|
||||
## Radarr
|
||||
|
||||
### Initial Setup
|
||||
|
||||
1st thing to do is load up your web browser and go to Radarr. In your URL bar put http://{IP-ADDRESS}:7878.
|
||||
|
||||
Putting in the IP of you Ubuntu machine. If you are using something like WSL just use localhost as IP.
|
||||
|
||||
You should be prompted to create an account. It doesn’t matter much if you choose Basic or Forms for authentication.
|
||||
|
||||
If you are starting fresh with no content, go to **Settings - Media Management - Root Folders** and add a root folder, you can use the movies folder that was located at /data/media/movies or you can go into /data/media and name your folders however you want to.
|
||||
|
||||
My media directory breaks down the movies by category: 4K, Movies, Marvel, DC, Kids, Stand-Up, Requested Content and Fights. They are added to Radarr individually as follows:
|
||||
|
||||

|
||||
|
||||
If you already have media you want to import into Radarr, click **Movies - Library Import - Start Import**. Remember all you files are going to be under /data/media if you followed my installation guide. This also adds the chosen directory as a root folder.
|
||||
|
||||
### Connect Sab to Radarr
|
||||
|
||||
To connect Sab to Radarr, in Radarr go to **Settings - Download Clients** - add - Sabnzbd - fill in all your Sab details, getting the API key from **Sab - General - Api Key** (Not NZB Key)
|
||||
|
||||
### Naming Files
|
||||
|
||||
It’s best practice to rename your files, Radarr does this automatically for you. To do this go to **Settings - Media Management - Movie Naming**. Make sure you check the Rename Movies checkbox. Everything should be fine by default besides Standard Movie Format, Jellyfin recommends this:
|
||||
|
||||
```
|
||||
{Movie CleanTitle} {(Release Year)} [imdbid-{ImdbId}] - {Edition Tags }{[Custom Formats]}{[Quality Full]}{[MediaInfo 3D]}{[MediaInfo VideoDynamicRangeType]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}[{Mediainfo VideoCodec}]{-Release Group}
|
||||
```
|
||||
|
||||
Make sure you hit save.
|
||||
|
||||
Note this only automatically renames the file if it was downloaded from Radarr, if you imported your own media you need to manually click rename files under **Movies** - Click Edit Movies - Select All - Rename Files on bottom of screen.
|
||||
|
||||
### Custom Formats
|
||||
|
||||
Every single one of these custom formats is from trash-guides, you can see how to import them [here](https://trash-guides.info/Radarr/Radarr-import-custom-formats/). 
|
||||
|
||||
Add all custom formats that you want to look out for, whether good or bad. What custom formats do is essentially put a label on files just based off the files name, as well as provide these labels a score which is used when auto-searching for a movie. Just adding custom formats on it’s own does nothing, setting up a Quality profile to rank these custom formats is how we pick and choose what we want. Reading through trash guides will yield good results.
|
||||
|
||||
### Quality Profiles
|
||||
|
||||
Now you need to ask yourself what your plan here is, do you want the highest possible quality content with no regards to storage space? Do you want a giant library filled with lower quality content? Do you have a 4K TV? Do you have HDR/HDR10/Dolby Vision on your TV? Do you have a Dolby Atmos system and want the top notch audio? What about the people you maybe plan on sharing these files with, do you know their TV’s capabilities? Are you gonna be using Plex or Jellyfin to stream this media?
|
||||
|
||||
You should consider all these things when setting this up so you don’t have to manually search for files. That’s the point of this whole section is to automate the searching process and find the correct kinds of files every time. Trash-Guides put together multiple flow charts on what custom formats to use in certain situations which can be found [here](https://trash-guides.info/Radarr/radarr-setup-quality-profiles/#which-quality-profile-should-you-choose)
|
||||
|
||||
I am going to put my logic behind how I have my setup configured, although you should review [this Trash-Guide](https://trash-guides.info/Radarr/radarr-setup-quality-profiles/) for more details.
|
||||
|
||||
1080P:  \*Not Shown custom format scores
|
||||
|
||||
- 3D:-10000
|
||||
- BR-DISK:-10000
|
||||
- Bad Dual Groups:-10000
|
||||
- EVO (no WEBDL):-10000
|
||||
- LQ (Release Title):-10000
|
||||
- x265 (HD):-10000 (This is Trash-Guides Golden Rule, 1080p=x264 | 4k=x265)
|
||||
|
||||
Not much logic here other than not getting crappy releases and only downloading x264 if its 1080P. File size limits can be put to get smaller files. I just follow [this](https://trash-guides.info/Radarr/Radarr-Quality-Settings-File-Size/).
|
||||
|
||||
I want x264 as its gonna have the highest compatibility with the most devices and the less transcoding I need to do the better.
|
||||
|
||||
4K:  
|
||||
|
||||
I have a 4K TV with Dolby Vision Support, along with a Dolby Atmos sound system. So making sure my 4K files have Dolby Vision is pretty important, also having the extended screen of IMAX on a home sized TV is amazing. Having both of those together is the perfect recipe IMO, yet not all movies support one or the other so not as common as you may think. But generally if I want something 4K it will have DV support. I read on trash guides that if you have DV files without DV HDR10 as a fallback, the video will appear off-color to TVs that don’t have DV. So I try to make sure DV with HDR10 fallback is 1st. File size is not taken into consideration at all, I have multiple ~90GB movies.
|
||||
|
||||
Also if your TV doesn’t have DV support, get one. In my experience the difference between HDR10/10+ and DV is night and day. And I usually am not a fan of proprietary software at all. The next best if you don’t have DV is HDR10+. But ultimately having any HDR is gonna be better than SDR.
|
||||
|
||||
I ended up removing the Atmos custom format as most of the time the insane high quality files will have Atmos, and it could just be my setup but I don’t notice too much a difference between DD+ and Atmos.
|
||||
|
||||
### Conclusion
|
||||
|
||||
With all this done you should be able to a add a new movie and watch it download over in Sab. Then when finished downloading it should be automatically moved to your target directory.
|
||||
|
||||
### Tips
|
||||
|
||||
1. If you ever find a file that works well and you don’t want Radarr to mess with it, unmonitor it. That way Radarr doesn’t upgrade it.
|
||||
2. If you are brand new to Radarr I would learn the basics of it in the web-ui, then proceed to utilizing the API with apps like [Nzb360](https://nzb360.com/), [LunaSea](https://www.lunasea.app/), and [Overseerr](https://overseerr.dev/) / [Jellyseerr](https://github.com/Fallenbagel/jellyseerr) to request stuff with a better front end. There’s even [Doplarr](https://docs.linuxserver.io/images/docker-doplarr/#application-setup) the Discord bot.
|
||||
3. Say you found a specific version of a movie, but the audio is bad or a different language, and you can’t find another video quality the same, you can use a tool called [mkvtoolnix](https://mkvtoolnix.download/) to merge audio tracks from one file to another’s video track. You will probably run into this at some point if you’re really looking for something specific.
|
||||
4. You can manually import Boxing/WWE/UFC events into Radarr and the metadata will apply, but searching in Radarr doesn’t work for these types of events. Manually finding the NZB’s or torrents and moving files seems to be only way.
|
||||
|
||||
## Sonarr
|
||||
|
||||
### Initial Setup
|
||||
|
||||
Sonarr is Radarr but for TV Shows.
|
||||
|
||||
First thing load up Sonarr on your web browser at http://{IP\_ADDRESS}:8989.
|
||||
|
||||
Make an account. Then do the same thing as Radarr and add a new root folder if starting new, or import your existing media. The root folder location should be /data/media/tv
|
||||
|
||||
Then we need to connect Sab to Sonarr, to do this Go to **Settings - Download Clients - Add** just like we did with Radarr, fill in all your Sab details.
|
||||
|
||||
### Custom Formats
|
||||
|
||||
Again all these custom formats are on trash-guides. Link [here](https://trash-guides.info/Sonarr/sonarr-collection-of-custom-formats/).  I just picked all major streaming services and the Tier’s. Import them the same way you did Radarr.
|
||||
|
||||
### Quality Profile
|
||||
|
||||
Go to **Settings - Profiles - Quality Profiles**  \*Not Shown custom format scores
|
||||
|
||||
- x265 (HD):-10000
|
||||
- BR-DISK:-10000
|
||||
|
||||
I only have this 1 1080p profile as I personally do not want to waste that storage space on a long TV series. I do not have any 4K TV shows at all. This generally always grabs the best available file. Again for Size Limit I follow [this trash-guide](https://trash-guides.info/Sonarr/Sonarr-Quality-Settings-File-Size/).
|
||||
|
||||
Having x265(HD) as -10000 means it will not download a 1080p file if it is encoded in x265, again this is for compatibility as x264 just works on more devices.
|
||||
|
||||
### Naming Files
|
||||
|
||||
I also rename Sonarr’s files, to do this go to **Settings - Media Management** - check Rename Episodes and under Standard Episode format set:
|
||||
|
||||
```
|
||||
{Series TitleYear} - S{season:00}E{episode:00} - {Episode CleanTitle} [{Custom Formats }{Quality Full}]{[MediaInfo VideoDynamicRangeType]}{[Mediainfo AudioCodec}{ Mediainfo AudioChannels]}{[MediaInfo VideoCodec]}{-Release Group}
|
||||
```
|
||||
|
||||
Make sure you save changes.
|
||||
|
||||
### Tips
|
||||
|
||||
1. Don’t download a whole series at once if it has many seasons, you may fill up on space on your VM. Which will stop everything on that VM. Usually they download faster than they transfer to target directory. So space can add up quick. I usually do 2-3 seasons at a time.
|
||||
|
||||
## Bazarr
|
||||
|
||||
Bazarr is used to get subtitles for all your content. Sometimes the files come with subtitle tracks, Bazarr covers you when they don’t.
|
||||
|
||||
### Initial Setup
|
||||
|
||||
First thing load up Bazarr on your web browser at http://{IP\_ADDRESS}:6767.
|
||||
|
||||
First thing is to set your language, go to **Settings - Languages - Languages Filter** and set the filter to your language. I set to English.
|
||||
|
||||
Then under Language Profiles click Add New Profile:
|
||||
|
||||
- Name: English
|
||||
- Click Add Language, english should pop up by default.
|
||||
- Set the cutoff to en
|
||||
- Save
|
||||
|
||||
At the bottom of this page there is Default Settings, check both boxes for Series and Movies and choose your language profile.
|
||||
|
||||
### Providers
|
||||
|
||||
Under **Settings - Providers** - Add a Provider:
|
||||
|
||||

|
||||
|
||||
YIFY, TVSubtitles, Supersubtitles, are all free and dont require an account.
|
||||
|
||||
opensubtitles.com requires you to create an account first but is free.
|
||||
|
||||
I have a OpenAI whisper model running on a separate VM which uses my GPU and AI to generate subtitles for content as well, And its pretty good even with the base model. It’s rarely needed as usually I find better subtitles thru another provider first with a higher score. But for those times when subtitles can’t be found its nice they can be generated. I found [this](https://wiki.bazarr.media/Additional-Configuration/Whisper-Provider/) in Bazarr’s docs.
|
||||
|
||||
Make sure you save your changes.
|
||||
|
||||
### Connecting Bazarr to Radarr/Sonarr
|
||||
|
||||
Now you just need to tell Bazarr where your arr’s are located. Go to **Settings - Sonarr** for Sonarr and **Settings - Radarr** for Radarr. Filling in all your details and saving.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Congrats you now have a fully automated backend for downloading media! Good time to cancel those 10 streaming subscriptions and start downloading what you wanna watch. There’s not many guides out there about this sort of thing, as piracy leaves some ethical concerns. But idrc, I’ve been a pirate my whole life, the fact that you can make a system like this all for way cheaper than streaming services is mind-blowing to me.
|
||||
|
||||
Now just hook up Jellyfin/Plex up to you /data/media directory and start watching with no ads!
|
||||
@@ -0,0 +1,493 @@
|
||||
|
||||
> ## ⚡ Want the easy, full version? → **[SparkBox](https://tomsparkbox.com)**
|
||||
>
|
||||
> This is one of my original one-shot scripts. It still works — but these days everything I build goes into **[SparkBox](https://tomsparkbo>
|
||||
>
|
||||
> ### 👉 Get it free at **[tomsparkbox.com](https://tomsparkbox.com)**
|
||||
>
|
||||
> _Built by [Tom Spark Reviews](https://youtube.com/@TomSparkReviews)._
|
||||
|
||||
---
|
||||
|
||||
# Tom Spark's ARR Stack
|
||||
|
||||
One-command automated media server with VPN protection. Sonarr, Radarr, Prowlarr, qBittorrent, Gluetun, Jellyfin, and more.
|
||||
|
||||
**Full video tutorial:** [YouTube Link Coming Soon]
|
||||
|
||||
## What You Get
|
||||
|
||||
| Service | Port | Purpose |
|
||||
|---------|------|---------|
|
||||
| Gluetun | — | VPN tunnel with kill switch |
|
||||
| qBittorrent | 8080 | Torrent client (VPN protected) |
|
||||
| Prowlarr | 9696 | Indexer manager (VPN protected) |
|
||||
| FlareSolverr | 8191 | Cloudflare bypass (VPN protected) |
|
||||
| Radarr | 7878 | Movie automation |
|
||||
| Sonarr | 8989 | TV show automation |
|
||||
| Lidarr | 8686 | Music automation |
|
||||
| Bazarr | 6767 | Subtitle automation |
|
||||
| Jellyfin | 8096 | Media server / streaming |
|
||||
| Seerr | 5055 | Netflix-like request UI (Overseerr/Jellyseerr successor) |
|
||||
|
||||
All download traffic routes through Gluetun's VPN tunnel. If the VPN drops, all traffic stops — zero leaks. The deunhealth container auto-r>
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Install Docker
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in for group change to take effect
|
||||
```
|
||||
|
||||
### 2. Clone this repo
|
||||
|
||||
```bash
|
||||
git clone https://github.com/loponai/arrstack.git
|
||||
cd arrstack
|
||||
```
|
||||
|
||||
### 3. Create folder structure
|
||||
|
||||
```bash
|
||||
sudo bash setup-folders.sh
|
||||
```
|
||||
|
||||
This creates:
|
||||
```
|
||||
/data/
|
||||
├── torrents/ ← qBittorrent downloads here
|
||||
│ ├── movies/
|
||||
│ ├── tv/
|
||||
│ └── music/
|
||||
└── media/ ← Radarr/Sonarr organize files here (Jellyfin reads from here)
|
||||
├── movies/
|
||||
├── tv/
|
||||
└── music/
|
||||
```
|
||||
|
||||
> **Hard links:** Both folders MUST be on the same drive/filesystem. Radarr and Sonarr create hard links (not copies) — the file appears in>
|
||||
|
||||
### 4. Configure your VPN
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Fill in your VPN provider and credentials. See [VPN Setup Guides](#vpn-setup-guides) below.
|
||||
|
||||
### 5. Launch
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 6. Verify everything is working
|
||||
|
||||
```bash
|
||||
bash test-stack.sh
|
||||
```
|
||||
|
||||
This runs a full health check — Docker status, VPN connection, IP leak test, service accessibility, hard link support, and folder permissio>
|
||||
|
||||
You can also check manually:
|
||||
```bash
|
||||
# Check Gluetun's IP (should be VPN, not your real IP)
|
||||
docker exec gluetun wget -qO- ifconfig.me
|
||||
|
||||
# qBittorrent shares Gluetun's network, so the above proves both are tunneled.
|
||||
docker exec qbittorrent wget -qO- ifconfig.me
|
||||
|
||||
# Check health status of all containers
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
### 7. Configure services
|
||||
|
||||
Open each service in your browser at `http://YOUR-SERVER-IP:PORT` and follow the video tutorial for step-by-step configuration.
|
||||
|
||||
**Quick reference:**
|
||||
- **qBittorrent** (`:8080`) — Get temp password: `docker logs qbittorrent 2>&1 | grep "temporary password"`
|
||||
- **Prowlarr** (`:9696`) — Add indexers, connect to Radarr/Sonarr. If an indexer is blocked by Cloudflare, set up FlareSolverr as a proxy: >
|
||||
- **Radarr** (`:7878`) — Root folder: `/data/media/movies`, download client category: `movies`
|
||||
- **Sonarr** (`:8989`) — Root folder: `/data/media/tv`, download client category: `tv`
|
||||
- **Jellyfin** (`:8096`) — Add libraries: `/data/media/movies`, `/data/media/tv`, `/data/media/music`. To watch, open `http://YOUR-SERVER-I>
|
||||
- **Seerr** (`:5055`) — Connect to Jellyfin, Radarr, and Sonarr. Seerr is the unified successor to Overseerr/Jellyseerr. If you previously >
|
||||
|
||||
**Internal Docker IPs — use these when connecting services to each other (NOT localhost):**
|
||||
|
||||
| IP | Service |
|
||||
|----|---------|
|
||||
| `172.39.0.2` | Gluetun (also qBittorrent, Prowlarr, FlareSolverr) |
|
||||
| `172.39.0.3` | Radarr |
|
||||
| `172.39.0.4` | Sonarr |
|
||||
| `172.39.0.5` | Lidarr |
|
||||
| `172.39.0.6` | Bazarr |
|
||||
| `172.39.0.7` | Jellyfin |
|
||||
| `172.39.0.8` | Seerr |
|
||||
|
||||
These IPs are the same for everyone — they're hardcoded in the docker-compose file.
|
||||
**Common connections:**
|
||||
- Radarr/Sonarr → Download Client → qBittorrent: host `172.39.0.2`, port `8080`
|
||||
- Prowlarr → Apps → Radarr: server `http://172.39.0.3:7878`
|
||||
- Prowlarr → Apps → Sonarr: server `http://172.39.0.4:8989`
|
||||
- Prowlarr → Apps → Prowlarr Server: `http://172.39.0.2:9696`
|
||||
- Seerr → Radarr: host `172.39.0.3`, port `7878`
|
||||
- Seerr → Sonarr: host `172.39.0.4`, port `8989`
|
||||
- Seerr → Jellyfin: host `172.39.0.7`, port `8096`
|
||||
|
||||
**Important Radarr/Sonarr settings:**
|
||||
- Media Management → Show Advanced → **Use Hardlinks instead of Copy** → must be ON
|
||||
- Media Management → **Rename Movies/Episodes** → recommended ON
|
||||
|
||||
**Recommended quality profile (1080p baseline, 4K preferred):**
|
||||
|
||||
Go to Settings → Profiles and edit or create a profile:
|
||||
1. Uncheck everything below 1080p (720p, 480p, etc.)
|
||||
2. Check/enable everything from **HDTV-1080p** up through **Bluray-2160p**
|
||||
3. Set **Cutoff** to `Bluray-1080p` — this is the minimum quality Radarr/Sonarr will be happy with
|
||||
4. Set **Upgrade Until** to `Bluray-2160p` — it will automatically upgrade to 4K if one becomes available
|
||||
|
||||
This means it grabs a 1080p release right away so you can start watching, then silently upgrades to 4K later if it finds one.
|
||||
|
||||
## VPN Setup Guides
|
||||
|
||||
### Surfshark (Recommended)
|
||||
The best value for torrenting — cheapest long-term plans, fast WireGuard speeds, and easy setup with Gluetun. [Get Surfshark](https://get.s>
|
||||
|
||||
1. Go to [Surfshark Manual Setup](https://my.surfshark.com/vpn/manual-setup/main)
|
||||
2. Select **WireGuard** and get your credentials (private key + address)
|
||||
3. In your `.env`:
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=surfshark
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.14.0.2/16
|
||||
SERVER_COUNTRIES=United States
|
||||
```
|
||||
|
||||
> The `.env.example` file is pre-configured for Surfshark. Just paste your private key and you're good to go.
|
||||
|
||||
### NordVPN
|
||||
1. Go to [NordVPN Manual Setup](https://my.nordaccount.com/dashboard/nordvpn/manual-configuration/)
|
||||
2. Select **NordLynx** (WireGuard) and generate a private key
|
||||
3. In your `.env`:
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=nordvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.5.0.2/16
|
||||
SERVER_COUNTRIES=United States
|
||||
```
|
||||
|
||||
### ProtonVPN
|
||||
1. Go to [ProtonVPN WireGuard Config](https://account.protonvpn.com/) → Downloads → WireGuard
|
||||
2. Generate a config file, open it, copy `PrivateKey` and `Address`
|
||||
3. In your `.env`:
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=protonvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.2.0.2/32
|
||||
SERVER_COUNTRIES=United States
|
||||
VPN_PORT_FORWARDING=on
|
||||
```
|
||||
### AirVPN
|
||||
1. Go to [AirVPN Config Generator](https://airvpn.org/) → Client Area → Config Generator
|
||||
2. Select Linux → WireGuard → pick server → Generate
|
||||
3. In your `.env`:
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=airvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_PUBLIC_KEY=server_public_key
|
||||
WIREGUARD_PRESHARED_KEY=your_preshared_key
|
||||
WIREGUARD_ADDRESSES=your_ip/32
|
||||
FIREWALL_VPN_INPUT_PORTS=your_port
|
||||
VPN_PORT_FORWARDING=on
|
||||
```
|
||||
|
||||
### Other Providers
|
||||
Gluetun supports 30+ providers. Check the [full provider list](https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers).
|
||||
|
||||
## Starting and Stopping
|
||||
|
||||
**Start the stack:**
|
||||
```bash
|
||||
cd arrstack
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Stop the stack:**
|
||||
```bash
|
||||
cd arrstack
|
||||
docker compose down
|
||||
```
|
||||
|
||||
**Check status:**
|
||||
```bash
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
### Auto-Start After Reboot
|
||||
|
||||
All containers are set to `restart: unless-stopped`, which means they automatically come back once Docker is running. You just need to make>
|
||||
|
||||
**Linux (dedicated server or VM):**
|
||||
|
||||
Run this once and you're done:
|
||||
```bash
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
**Windows (running Docker inside WSL):**
|
||||
|
||||
WSL (Windows Subsystem for Linux) doesn't start Docker automatically when your PC boots. Here's how to fix that:
|
||||
|
||||
**Step 1:** Open your WSL terminal and run this command to edit the WSL config file:
|
||||
```bash
|
||||
sudo nano /etc/wsl.conf
|
||||
```
|
||||
|
||||
**Step 2:** Your file might already have some lines in it (like `[boot]` or `[user]`). Look for a `[boot]` section. If it exists, add the `>
|
||||
```ini
|
||||
[boot]
|
||||
command=service docker start
|
||||
```
|
||||
|
||||
**Step 3:** Save the file by pressing `Ctrl+X`, then `Y`, then `Enter`.
|
||||
**Step 4 (optional):** By default, WSL only starts when you open a terminal. If you want it to start automatically when Windows boots (so y>
|
||||
|
||||
1. Press `Win+R` on your keyboard
|
||||
2. Type `shell:startup` and press Enter — this opens your Windows Startup folder
|
||||
3. Right-click in the folder → New → Text Document
|
||||
4. Name it `wsl.vbs` (make sure it ends in `.vbs`, not `.vbs.txt` — if you can't see file extensions, go to View → Show → File name extensi>
|
||||
5. Right-click the file → Edit (or Open with Notepad) and paste this:
|
||||
```vbs
|
||||
Set ws = CreateObject("Wscript.Shell")
|
||||
ws.Run "wsl -d Ubuntu -u root -- service docker start", 0
|
||||
```
|
||||
6. Save and close
|
||||
|
||||
That's it — next time your PC restarts, WSL starts Docker automatically and all your containers come back up on their own. No commands need>
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
cd arrstack
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Remote Access with Tailscale (Optional)
|
||||
|
||||
Want to access Jellyfin, Seerr, or any service from outside your home? [Tailscale](https://tailscale.com/) creates a private network betwee>
|
||||
|
||||
**On your server:**
|
||||
```bash
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
sudo tailscale up
|
||||
```
|
||||
|
||||
**On your phone/laptop/TV:**
|
||||
1. Install Tailscale from your app store
|
||||
2. Sign in with the same account
|
||||
|
||||
**Access your services from anywhere:**
|
||||
```
|
||||
http://YOUR-TAILSCALE-IP:8096 ← Jellyfin
|
||||
http://YOUR-TAILSCALE-IP:5055 ← Seerr
|
||||
http://YOUR-TAILSCALE-IP:7878 ← Radarr
|
||||
http://YOUR-TAILSCALE-IP:8989 ← Sonarr
|
||||
```
|
||||
|
||||
Find your Tailscale IP with `tailscale ip -4` on the server.
|
||||
|
||||
Tailscale is free for personal use (up to 100 devices). Everything is encrypted with WireGuard — nobody can see your traffic, not even Tail>
|
||||
|
||||
> **Do NOT expose Jellyfin directly to the internet** (no port forwarding on your router). Use Tailscale or a reverse proxy instead. Direct>
|
||||
|
||||
### Sharing with Family and Friends
|
||||
|
||||
Your family and friends only need two things — **Seerr** to request movies/shows and **Jellyfin** to watch them. They never see Radarr, Son>
|
||||
|
||||
**Step 1: Invite them to your Tailscale network**
|
||||
|
||||
1. Go to the [Tailscale admin console](https://login.tailscale.com/admin/machines)
|
||||
2. Click **Share** on your server's machine
|
||||
3. Enter their email — they'll get an invite link
|
||||
|
||||
**Step 2: They install Tailscale**
|
||||
|
||||
1. Download Tailscale on their phone, laptop, or TV from [tailscale.com/download](https://tailscale.com/download)
|
||||
2. Accept your invite and sign in
|
||||
**Step 3: They access your services**
|
||||
|
||||
Give them these two links (replace with your Tailscale IP):
|
||||
```
|
||||
http://YOUR-TAILSCALE-IP:5055 ← Seerr (request movies and shows)
|
||||
http://YOUR-TAILSCALE-IP:8096 ← Jellyfin (watch everything)
|
||||
```
|
||||
|
||||
**For TVs and phones**, they can install the **Jellyfin app** (available on Roku, Fire TV, Apple TV, Android TV, iOS, Android) and enter yo>
|
||||
|
||||
That's it — they request, you automatically download, they watch. No technical knowledge needed on their end.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Gluetun unhealthy / won't connect:**
|
||||
- Double-check VPN credentials in `.env` — these are NOT your login email/password
|
||||
- Try removing the gluetun folder and restarting: `rm -rf gluetun && docker compose up -d`
|
||||
- Check logs: `docker logs gluetun`
|
||||
|
||||
**qBittorrent can't connect:**
|
||||
- Make sure Gluetun is healthy: `docker ps` (should show "healthy")
|
||||
- Check qBit is using VPN: `docker exec gluetun wget -qO- ifconfig.me`
|
||||
- In qBittorrent settings → Advanced → set Network Interface to `tun0`
|
||||
|
||||
**Movie or show not downloading:**
|
||||
- **Quality profile too strict** — If Radarr/Sonarr can't find a release matching your quality profile, it won't download anything. Go to t>
|
||||
- **Not enough indexers** — Public indexers have limited catalogs. If you only have one or two indexers in Prowlarr, add more (1337x, The P>
|
||||
- **Not enough seeders** — Some torrents just don't have anyone sharing them, especially older or niche content. Check qBittorrent — if the>
|
||||
- **Indexer blocked by Cloudflare** — See the Prowlarr setup note above about setting up FlareSolverr with tags.
|
||||
|
||||
**Hard links not working (files copying instead):**
|
||||
- Both `/data/torrents` and `/data/media` must be on the same filesystem
|
||||
- Check Radarr/Sonarr → Settings → Media Management → "Use Hardlinks" is checked
|
||||
- Verify with: `ls -i /data/torrents/movies/yourfile` and `ls -i /data/media/movies/YourMovie/yourfile` — inode numbers should match
|
||||
|
||||
**Permission errors:**
|
||||
- Run `id` and make sure PUID/PGID in `.env` match your user
|
||||
- Re-run: `sudo chown -R $(id -u):$(id -g) /data`
|
||||
|
||||
**Service won't start — "port already in use":**
|
||||
|
||||
Another program on your system might be using the same port. This is common with port 5055 (Seerr) but can happen with any service.
|
||||
|
||||
1. Find what's using the port (replace `5055` with the port number from the error):
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
sudo ss -tlnp | grep 5055
|
||||
```
|
||||
|
||||
**Windows (WSL users) — run in PowerShell:**
|
||||
```powershell
|
||||
netstat -ano | findstr :5055
|
||||
```
|
||||
This gives you a PID (process ID). Find the program name:
|
||||
```powershell
|
||||
Get-Process -Id <PID> | Select-Object ProcessName, Id, Path
|
||||
```
|
||||
|
||||
2. Either stop/disable that program, or change the port in `docker-compose.yml` to an unused one (e.g. `5056:5055`).
|
||||
|
||||
3. If it's a Windows service hogging the port, disable it in an admin PowerShell:
|
||||
```powershell
|
||||
Stop-Service <ServiceName> -Force
|
||||
Set-Service <ServiceName> -StartupType Disabled
|
||||
```
|
||||
4. Then recreate the container:
|
||||
```bash
|
||||
docker compose up -d --force-recreate <service-name>
|
||||
```
|
||||
|
||||
**Seerr stuck restarting / crash-looping:**
|
||||
|
||||
The current `docker-compose.yml` uses a named volume (`seerr_config`) for Seerr's config, which fixes both causes of the crash loop. If you>
|
||||
|
||||
Root cause (for reference):
|
||||
- **Linux/macOS:** Seerr runs as the `node` user (UID 1000). A bind-mounted `./seerr` folder is created root-owned on first `docker compose>
|
||||
- **Windows/WSL:** Bind mounts go through an SMB share inside Docker Desktop's VM, which doesn't support file locking. Seerr's SQLite DB co>
|
||||
|
||||
Named volumes sidestep both problems because Docker creates them with correct ownership inside its own managed storage.
|
||||
|
||||
If you still see it after pulling:
|
||||
- Check logs: `docker logs seerr | tail -30`
|
||||
- Nuke the volume and start fresh (you'll lose Seerr settings, not media):
|
||||
```bash
|
||||
docker compose down seerr && docker volume rm arrstack_seerr_config && docker compose up -d seerr
|
||||
```
|
||||
|
||||
**Migrating Seerr config to a named volume (existing installs):**
|
||||
|
||||
If you had Seerr working on an older version of this repo with a bind-mounted `./jellyseerr` or `./seerr` folder and want to keep your sett>
|
||||
|
||||
```bash
|
||||
docker compose down seerr
|
||||
# pick whichever folder you actually have
|
||||
SRC=./seerr
|
||||
[ -d ./jellyseerr ] && SRC=./jellyseerr
|
||||
docker volume create arrstack_seerr_config
|
||||
docker run --rm -v "$(pwd)/${SRC#./}":/src -v arrstack_seerr_config:/dest alpine sh -c "cp -a /src/. /dest/ && chown -R 1000:1000 /dest"
|
||||
docker compose up -d seerr
|
||||
```
|
||||
|
||||
If you don't care about preserving settings, just `docker compose up -d seerr` — Seerr will start fresh and walk you through setup again.
|
||||
|
||||
**Can't log into qBittorrent:**
|
||||
- qBittorrent generates a temporary password every time it starts. Get it with:
|
||||
```bash
|
||||
docker logs qbittorrent 2>&1 | grep "temporary password"
|
||||
```
|
||||
- Default username is `admin`. Once logged in, go to Tools → Options → Web UI and set a permanent password.
|
||||
|
||||
**Services can't connect to each other (connection refused, timeout):**
|
||||
- Don't use `localhost` when connecting services together — that won't work across Docker containers.
|
||||
- Use the internal Docker IPs instead:
|
||||
- qBittorrent/Prowlarr/FlareSolverr: `172.39.0.2`
|
||||
- Radarr: `172.39.0.3`
|
||||
- Sonarr: `172.39.0.4`
|
||||
- Jellyfin: `172.39.0.7`
|
||||
- The one exception: Prowlarr → FlareSolverr can use `localhost:8191` because they both run through Gluetun and share the same network.
|
||||
|
||||
**"Root folder does not exist" in Radarr/Sonarr:**
|
||||
- Make sure you ran `sudo bash setup-folders.sh` to create the `/data` directory structure.
|
||||
- Double-check the root folder path — it should be `/data/media/movies` for Radarr and `/data/media/tv` for Sonarr (not `/movies` or `/data>
|
||||
|
||||
**Downloads stuck at "importing" or "waiting to import":**
|
||||
- This is almost always a permissions issue. Fix it with:
|
||||
```bash
|
||||
sudo chown -R $(id -u):$(id -g) /data
|
||||
sudo chmod -R 775 /data
|
||||
```
|
||||
- Make sure PUID/PGID in your `.env` match your user (check with `id`).
|
||||
**Jellyfin library is empty after downloads finish:**
|
||||
- Make sure your Jellyfin libraries point to the correct paths: `/data/media/movies`, `/data/media/tv`, `/data/media/music`
|
||||
- Jellyfin doesn't scan instantly. Go to Dashboard → Libraries → click the `...` menu → **Scan Library** to force a refresh.
|
||||
- You can also set up scheduled scans in Dashboard → Scheduled Tasks.
|
||||
|
||||
**Subtitles not downloading (Bazarr):**
|
||||
- Bazarr needs to be connected to Radarr and Sonarr: Settings → Radarr / Sonarr → enter the IP (`172.39.0.3` / `172.39.0.4`) and API key.
|
||||
- You also need at least one subtitle provider: Settings → Providers → Add → **OpenSubtitles.com** is the most popular (free account requir>
|
||||
|
||||
**Everything works but downloads are slow:**
|
||||
- Your VPN server might be too far away. Change `SERVER_COUNTRIES` in your `.env` to a country closer to you, then restart:
|
||||
```bash
|
||||
docker compose down && docker compose up -d
|
||||
```
|
||||
- Check your VPN speed: `docker exec gluetun wget -qO- https://speed.cloudflare.com/__down?measId=10000000 > /dev/null` — if it's very slow>
|
||||
|
||||
**Disk space filling up:**
|
||||
- By default, qBittorrent keeps torrents after Radarr/Sonarr imports them. To auto-clean:
|
||||
- In Radarr/Sonarr → Settings → Download Clients → click on qBittorrent → enable **Remove Completed**
|
||||
- This deletes the torrent from qBittorrent after the file has been imported (the hard link in your media folder is kept, so you don't lo>
|
||||
|
||||
**VPN IP leak — want to make sure your real IP isn't exposed:**
|
||||
```bash
|
||||
# Check the VPN container's IP (should NOT be your real IP)
|
||||
docker exec gluetun wget -qO- ifconfig.me
|
||||
|
||||
# Compare with your real IP (run this outside Docker)
|
||||
curl -s ifconfig.me
|
||||
```
|
||||
If both IPs are the same, your VPN isn't working — check Gluetun logs with `docker logs gluetun`.
|
||||
|
||||
## Credits
|
||||
|
||||
Built by [Tom Spark](https://youtube.com/@tomspark) following [Trash Guides](https://trash-guides.info/) and [Servarr Wiki](https://wiki.se>
|
||||
|
||||
Uses [Gluetun](https://github.com/qdm12/gluetun) for VPN, [LinuxServer.io](https://linuxserver.io) container images, and [Seerr](https://gi>
|
||||
@@ -0,0 +1,66 @@
|
||||
```
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# Tom Spark's ARR Stack — Folder Structure Setup
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# Creates the /data directory structure required for hard links
|
||||
# to work correctly. Run this ONCE before starting the stack.
|
||||
#
|
||||
# Usage: sudo bash setup-folders.sh
|
||||
# ============================================================
|
||||
|
||||
set -e
|
||||
|
||||
DATA_DIR="/data"
|
||||
|
||||
echo ""
|
||||
echo "=== Tom Spark's ARR Stack — Folder Setup ==="
|
||||
echo ""
|
||||
echo "This will create the following structure:"
|
||||
echo ""
|
||||
echo " /data/"
|
||||
echo " ├── torrents/"
|
||||
echo " │ ├── movies/"
|
||||
echo " │ ├── tv/"
|
||||
echo " │ └── music/"
|
||||
echo " └── media/"
|
||||
echo " ├── movies/"
|
||||
echo " ├── tv/"
|
||||
echo " └── music/"
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "ERROR: This script needs sudo to create /data and set permissions."
|
||||
echo "Run: sudo bash setup-folders.sh"
|
||||
exit 1
|
||||
fi
|
||||
# Get the real user (not root) for ownership
|
||||
REAL_USER=${SUDO_USER:-$USER}
|
||||
REAL_UID=$(id -u "$REAL_USER")
|
||||
REAL_GID=$(id -g "$REAL_USER")
|
||||
|
||||
echo "Creating folders..."
|
||||
mkdir -p "$DATA_DIR"/{torrents/{movies,tv,music},media/{movies,tv,music}}
|
||||
|
||||
echo "Setting ownership to $REAL_USER ($REAL_UID:$REAL_GID)..."
|
||||
chown -R "$REAL_UID":"$REAL_GID" "$DATA_DIR"
|
||||
|
||||
echo "Setting permissions..."
|
||||
chmod -R 775 "$DATA_DIR"
|
||||
|
||||
echo ""
|
||||
echo "Done! Folder structure:"
|
||||
if command -v tree &> /dev/null; then
|
||||
tree "$DATA_DIR"
|
||||
else
|
||||
find "$DATA_DIR" -type d | head -20
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Your PUID=$REAL_UID and PGID=$REAL_GID"
|
||||
echo "Make sure these match your .env file."
|
||||
echo ""
|
||||
|
||||
```
|
||||
@@ -0,0 +1,328 @@
|
||||
```
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# Tom Spark's ARR Stack — Health Check & Troubleshooting
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# Run this after 'docker compose up -d' to verify everything
|
||||
# is working correctly. It checks each service, tests VPN
|
||||
# connectivity, and provides specific fixes for any issues.
|
||||
#
|
||||
# Usage: bash test-stack.sh
|
||||
# ============================================================
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
PASS="${GREEN}✓ PASS${NC}"
|
||||
FAIL="${RED}✗ FAIL${NC}"
|
||||
WARN="${YELLOW}! WARN${NC}"
|
||||
TOTAL_PASS=0
|
||||
TOTAL_FAIL=0
|
||||
TOTAL_WARN=0
|
||||
|
||||
pass() { echo -e " ${PASS} $1"; ((TOTAL_PASS++)); }
|
||||
fail() { echo -e " ${FAIL} $1"; ((TOTAL_FAIL++)); }
|
||||
warn() { echo -e " ${WARN} $1"; ((TOTAL_WARN++)); }
|
||||
header() { echo -e "\n${CYAN}${BOLD}[$1]${NC}"; }
|
||||
fix() { echo -e " ${YELLOW}Fix: $1${NC}"; }
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo " Tom Spark's ARR Stack — Health Check"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# TEST 1: Docker running?
|
||||
# ============================================================
|
||||
header "Docker"
|
||||
if docker info > /dev/null 2>&1; then
|
||||
pass "Docker is running"
|
||||
else
|
||||
fail "Docker is not running"
|
||||
fix "Start Docker: sudo systemctl start docker"
|
||||
fix "Or install: curl -fsSL https://get.docker.com | sh"
|
||||
echo ""
|
||||
echo "Cannot continue without Docker. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# TEST 2: .env file exists and has VPN credentials?
|
||||
# ============================================================
|
||||
header "Configuration"
|
||||
|
||||
if [ -f .env ]; then
|
||||
pass ".env file exists"
|
||||
else
|
||||
fail ".env file not found"
|
||||
fix "Run: cp .env.example .env && nano .env"
|
||||
fix "Then fill in your VPN credentials"
|
||||
fi
|
||||
|
||||
if [ -f .env ]; then
|
||||
VPN_KEY=$(grep -E "^WIREGUARD_PRIVATE_KEY=" .env 2>/dev/null | cut -d= -f2)
|
||||
VPN_PROVIDER=$(grep -E "^VPN_SERVICE_PROVIDER=" .env 2>/dev/null | cut -d= -f2)
|
||||
|
||||
if [ -n "$VPN_KEY" ] && [ "$VPN_KEY" != "" ]; then
|
||||
pass "VPN private key is set (provider: $VPN_PROVIDER)"
|
||||
else
|
||||
fail "VPN private key is empty"
|
||||
fix "Edit .env and paste your WireGuard private key"
|
||||
fix "Get it from your VPN provider's manual setup page"
|
||||
fi
|
||||
fi
|
||||
# ============================================================
|
||||
# TEST 3: Folder structure exists?
|
||||
# ============================================================
|
||||
header "Folder Structure"
|
||||
|
||||
ALL_FOLDERS_OK=true
|
||||
for dir in /data/torrents/movies /data/torrents/tv /data/torrents/music /data/media/movies /data/media/tv /data/media/music; do
|
||||
if [ -d "$dir" ]; then
|
||||
pass "$dir exists"
|
||||
else
|
||||
fail "$dir missing"
|
||||
ALL_FOLDERS_OK=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ALL_FOLDERS_OK" = false ]; then
|
||||
fix "Run: sudo bash setup-folders.sh"
|
||||
fi
|
||||
|
||||
# Check permissions
|
||||
if [ -d /data ]; then
|
||||
OWNER=$(stat -c '%u' /data 2>/dev/null)
|
||||
ENV_PUID=$(grep -E "^PUID=" .env 2>/dev/null | cut -d= -f2)
|
||||
if [ "$OWNER" = "$ENV_PUID" ] || [ "$OWNER" = "$(id -u)" ]; then
|
||||
pass "/data ownership matches PUID ($OWNER)"
|
||||
else
|
||||
warn "/data owned by $OWNER but PUID is ${ENV_PUID:-1000}"
|
||||
fix "Run: sudo chown -R ${ENV_PUID:-1000}:${ENV_PUID:-1000} /data"
|
||||
fi
|
||||
fi
|
||||
# ============================================================
|
||||
# TEST 4: Container status
|
||||
# ============================================================
|
||||
header "Containers"
|
||||
|
||||
EXPECTED_SERVICES="gluetun qbittorrent deunhealth prowlarr flaresolverr radarr sonarr lidarr bazarr jellyfin seerr"
|
||||
|
||||
for svc in $EXPECTED_SERVICES; do
|
||||
STATUS=$(docker inspect --format '{{.State.Status}}' "$svc" 2>/dev/null)
|
||||
HEALTH=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}no-healthcheck{{end}}' "$svc" 2>/dev/null)
|
||||
|
||||
if [ -z "$STATUS" ]; then
|
||||
fail "$svc — not found (not created)"
|
||||
fix "Run: docker compose up -d"
|
||||
elif [ "$STATUS" = "running" ]; then
|
||||
if [ "$HEALTH" = "healthy" ]; then
|
||||
pass "$svc — running (healthy)"
|
||||
elif [ "$HEALTH" = "unhealthy" ]; then
|
||||
fail "$svc — running but UNHEALTHY"
|
||||
if [ "$svc" = "gluetun" ]; then
|
||||
fix "VPN probably can't connect. Check credentials in .env"
|
||||
fix "Check logs: docker logs gluetun | tail -20"
|
||||
fix "Try: rm -rf gluetun && docker compose up -d gluetun"
|
||||
elif [ "$svc" = "qbittorrent" ]; then
|
||||
fix "Usually means VPN dropped. Deunhealth should auto-restart it."
|
||||
fix "Check: docker logs qbittorrent | tail -20"
|
||||
fi
|
||||
elif [ "$HEALTH" = "starting" ]; then
|
||||
warn "$svc — running (health check starting, wait 30s and rerun)"
|
||||
else
|
||||
pass "$svc — running"
|
||||
fi
|
||||
elif [ "$STATUS" = "created" ]; then
|
||||
warn "$svc — created but not started"
|
||||
if [ "$svc" = "qbittorrent" ] || [ "$svc" = "prowlarr" ] || [ "$svc" = "flaresolverr" ]; then
|
||||
fix "Waiting for Gluetun to be healthy. Check Gluetun status first."
|
||||
fix "If Gluetun is healthy, try: docker compose up -d $svc"
|
||||
elif [ "$svc" = "seerr" ]; then
|
||||
fix "Port 5055 may be in use. Check: ss -tlnp | grep 5055"
|
||||
fix "Or change the port in docker-compose.yml"
|
||||
else
|
||||
fix "Try: docker compose up -d $svc"
|
||||
fi
|
||||
elif [ "$STATUS" = "restarting" ]; then
|
||||
fail "$svc — crash-looping (restarting)"
|
||||
fix "Check logs: docker logs $svc | tail -30"
|
||||
if [ "$svc" = "seerr" ]; then
|
||||
fix "Seerr may have a corrupt config. Try: docker compose down seerr && rm -rf seerr && docker compose up -d seerr"
|
||||
fix "WSL/Windows users: if it keeps crashing, try a named volume instead of a bind mount"
|
||||
else
|
||||
fix "Try: docker compose down $svc && docker compose up -d $svc"
|
||||
fi
|
||||
elif [ "$STATUS" = "exited" ]; then
|
||||
fail "$svc — exited (crashed)"
|
||||
fix "Check logs: docker logs $svc | tail -30"
|
||||
fix "Try restarting: docker compose up -d $svc"
|
||||
else
|
||||
warn "$svc — status: $STATUS"
|
||||
fi
|
||||
done
|
||||
# ============================================================
|
||||
# TEST 5: VPN connectivity
|
||||
# ============================================================
|
||||
header "VPN Connection"
|
||||
|
||||
GLUETUN_STATUS=$(docker inspect --format '{{.State.Status}}' gluetun 2>/dev/null)
|
||||
GLUETUN_HEALTH=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{end}}' gluetun 2>/dev/null)
|
||||
|
||||
if [ "$GLUETUN_STATUS" = "running" ] && [ "$GLUETUN_HEALTH" = "healthy" ]; then
|
||||
# Get VPN IP
|
||||
VPN_IP=$(docker exec gluetun wget -qO- --timeout=10 ipinfo.io/ip 2>/dev/null)
|
||||
if [ -n "$VPN_IP" ]; then
|
||||
pass "Gluetun VPN IP: $VPN_IP"
|
||||
|
||||
# Get VPN location
|
||||
VPN_LOCATION=$(docker exec gluetun wget -qO- --timeout=10 "ipinfo.io/${VPN_IP}/city" 2>/dev/null)
|
||||
VPN_COUNTRY=$(docker exec gluetun wget -qO- --timeout=10 "ipinfo.io/${VPN_IP}/country" 2>/dev/null)
|
||||
if [ -n "$VPN_LOCATION" ]; then
|
||||
pass "VPN location: $VPN_LOCATION, $VPN_COUNTRY"
|
||||
fi
|
||||
else
|
||||
fail "Gluetun is healthy but can't reach the internet"
|
||||
fix "Check logs: docker logs gluetun | tail -20"
|
||||
fi
|
||||
|
||||
# Check if qBittorrent is tunneled
|
||||
QBIT_STATUS=$(docker inspect --format '{{.State.Status}}' qbittorrent 2>/dev/null)
|
||||
if [ "$QBIT_STATUS" = "running" ]; then
|
||||
QBIT_IP=$(docker exec qbittorrent wget -qO- --timeout=10 ipinfo.io/ip 2>/dev/null)
|
||||
if [ "$QBIT_IP" = "$VPN_IP" ]; then
|
||||
pass "qBittorrent tunneled through VPN ($QBIT_IP)"
|
||||
elif [ -n "$QBIT_IP" ]; then
|
||||
fail "qBittorrent IP ($QBIT_IP) doesn't match VPN IP ($VPN_IP)!"
|
||||
fix "This should not happen. Check network_mode in docker-compose.yml"
|
||||
else
|
||||
warn "Could not check qBittorrent IP (container may still be starting)"
|
||||
fi
|
||||
fi
|
||||
# Check if Prowlarr is tunneled
|
||||
PROWLARR_STATUS=$(docker inspect --format '{{.State.Status}}' prowlarr 2>/dev/null)
|
||||
if [ "$PROWLARR_STATUS" = "running" ]; then
|
||||
PROWLARR_IP=$(docker exec prowlarr wget -qO- --timeout=10 ipinfo.io/ip 2>/dev/null)
|
||||
if [ "$PROWLARR_IP" = "$VPN_IP" ]; then
|
||||
pass "Prowlarr tunneled through VPN ($PROWLARR_IP)"
|
||||
elif [ -n "$PROWLARR_IP" ]; then
|
||||
fail "Prowlarr IP ($PROWLARR_IP) doesn't match VPN IP ($VPN_IP)!"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify your real IP is different
|
||||
REAL_IP=$(wget -qO- --timeout=10 ipinfo.io/ip 2>/dev/null)
|
||||
if [ -n "$REAL_IP" ] && [ "$REAL_IP" != "$VPN_IP" ]; then
|
||||
pass "Real IP ($REAL_IP) differs from VPN IP — VPN is working!"
|
||||
elif [ "$REAL_IP" = "$VPN_IP" ]; then
|
||||
warn "Real IP matches VPN IP — are you already running a system-wide VPN?"
|
||||
fi
|
||||
else
|
||||
if [ "$GLUETUN_HEALTH" = "unhealthy" ]; then
|
||||
fail "Gluetun is unhealthy — VPN not connected"
|
||||
fix "Check credentials in .env (these are NOT your VPN login email/password)"
|
||||
fix "Check logs: docker logs gluetun 2>&1 | tail -30"
|
||||
fix "Try resetting: docker compose down && rm -rf gluetun && docker compose up -d"
|
||||
elif [ "$GLUETUN_HEALTH" = "starting" ]; then
|
||||
warn "Gluetun health check still starting — wait 30-60 seconds and rerun"
|
||||
else
|
||||
warn "Gluetun not running — can't test VPN"
|
||||
fix "Run: docker compose up -d"
|
||||
fi
|
||||
fi
|
||||
# ============================================================
|
||||
# TEST 6: Service web UI accessibility
|
||||
# ============================================================
|
||||
header "Web UI Access"
|
||||
|
||||
check_http() {
|
||||
local name=$1 port=$2
|
||||
local code=$(curl -sL -o /dev/null -w "%{http_code}" --max-time 5 "http://localhost:$port" 2>/dev/null)
|
||||
if [ "$code" = "200" ] || [ "$code" = "302" ] || [ "$code" = "301" ] || [ "$code" = "307" ]; then
|
||||
pass "$name — http://localhost:$port (HTTP $code)"
|
||||
elif [ "$code" = "000" ]; then
|
||||
# Container might be behind gluetun, check if it's running
|
||||
local status=$(docker inspect --format '{{.State.Status}}' "$name" 2>/dev/null)
|
||||
if [ "$status" = "running" ]; then
|
||||
warn "$name — container running but port $port not reachable from host"
|
||||
fix "Port may be mapped on Gluetun. Try: http://localhost:$port"
|
||||
else
|
||||
fail "$name — not reachable (container not running)"
|
||||
fi
|
||||
else
|
||||
warn "$name — http://localhost:$port returned HTTP $code"
|
||||
fi
|
||||
}
|
||||
|
||||
check_http qbittorrent 8080
|
||||
check_http prowlarr 9696
|
||||
check_http radarr 7878
|
||||
check_http sonarr 8989
|
||||
check_http lidarr 8686
|
||||
check_http bazarr 6767
|
||||
check_http jellyfin 8096
|
||||
check_http seerr 5055
|
||||
# ============================================================
|
||||
# TEST 7: Hard link capability
|
||||
# ============================================================
|
||||
header "Hard Links"
|
||||
|
||||
if [ -d /data/torrents ] && [ -d /data/media ]; then
|
||||
# Check if same filesystem
|
||||
FS_TORRENTS=$(df /data/torrents --output=source 2>/dev/null | tail -1)
|
||||
FS_MEDIA=$(df /data/media --output=source 2>/dev/null | tail -1)
|
||||
|
||||
if [ "$FS_TORRENTS" = "$FS_MEDIA" ]; then
|
||||
pass "torrents/ and media/ are on the same filesystem ($FS_TORRENTS)"
|
||||
pass "Hard links will work correctly"
|
||||
else
|
||||
fail "torrents/ ($FS_TORRENTS) and media/ ($FS_MEDIA) are on DIFFERENT filesystems!"
|
||||
fix "Hard links only work on the same filesystem/drive"
|
||||
fix "Move both directories to the same drive"
|
||||
fi
|
||||
|
||||
# Quick hard link test
|
||||
TEST_FILE="/data/torrents/.hardlink_test_$$"
|
||||
TEST_LINK="/data/media/.hardlink_test_$$"
|
||||
if touch "$TEST_FILE" 2>/dev/null && ln "$TEST_FILE" "$TEST_LINK" 2>/dev/null; then
|
||||
pass "Hard link test succeeded"
|
||||
rm -f "$TEST_FILE" "$TEST_LINK" 2>/dev/null
|
||||
elif [ -f "$TEST_FILE" ]; then
|
||||
fail "Hard link test failed — filesystem may not support hard links"
|
||||
fix "Check filesystem type: df -T /data"
|
||||
fix "Hard links work on ext4, btrfs, xfs. NOT on exFAT or ntfs-3g"
|
||||
rm -f "$TEST_FILE" 2>/dev/null
|
||||
else
|
||||
warn "Could not write to /data/torrents (permission issue?)"
|
||||
fix "Run: sudo chown -R $(id -u):$(id -g) /data"
|
||||
fi
|
||||
else
|
||||
warn "Folder structure not found — skipping hard link test"
|
||||
fix "Run: sudo bash setup-folders.sh"
|
||||
fi
|
||||
# ============================================================
|
||||
# SUMMARY
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo -e " ${GREEN}Passed: $TOTAL_PASS${NC} ${RED}Failed: $TOTAL_FAIL${NC} ${YELLOW}Warnings: $TOTAL_WARN${NC}"
|
||||
echo "========================================="
|
||||
|
||||
if [ $TOTAL_FAIL -eq 0 ] && [ $TOTAL_WARN -eq 0 ]; then
|
||||
echo -e "\n ${GREEN}${BOLD}All checks passed! Your stack is ready to go.${NC}\n"
|
||||
elif [ $TOTAL_FAIL -eq 0 ]; then
|
||||
echo -e "\n ${YELLOW}${BOLD}No failures, but check the warnings above.${NC}\n"
|
||||
else
|
||||
echo -e "\n ${RED}${BOLD}Some checks failed. Follow the fix instructions above.${NC}"
|
||||
echo -e " ${BOLD}If stuck, check: docker logs <container-name>${NC}\n"
|
||||
fi
|
||||
```
|
||||
+546
@@ -0,0 +1,546 @@
|
||||
---
|
||||
title: "loponai/arrstack: One-command media server (Sonarr/Radarr/Prowlarr/qBittorrent behind a VPN). Now maintained as SparkBox → tomsparkbox.com"
|
||||
source: https://github.com/loponai/arrstack
|
||||
author:
|
||||
published:
|
||||
created: 2026-07-09
|
||||
description: One-command media server (Sonarr/Radarr/Prowlarr/qBittorrent behind a VPN). Now maintained as SparkBox → tomsparkbox.com - loponai/arrstack
|
||||
tags:
|
||||
- clippings
|
||||
- Media
|
||||
---
|
||||
> ## ⚡ Want the easy, full version? → SparkBox
|
||||
>
|
||||
> This is one of my original one-shot scripts. It still works — but these days everything I build goes into **[SparkBox](https://tomsparkbox.com/)**: a free, self-hosted home server that sets up this whole stack (and a lot more — photos, files, password manager, ad-blocking) with **one command**, a real web dashboard, automatic updates with one-click rollback, and a built-in AI assistant that troubleshoots and fixes things for you. No hand-editing config files.
|
||||
>
|
||||
> ### 👉 Get it free at tomsparkbox.com
|
||||
>
|
||||
> *Built by [Tom Spark Reviews](https://youtube.com/@TomSparkReviews).*
|
||||
|
||||
---
|
||||
|
||||
## Tom Spark's ARR Stack
|
||||
|
||||
One-command automated media server with VPN protection. Sonarr, Radarr, Prowlarr, qBittorrent, Gluetun, Jellyfin, and more.
|
||||
|
||||
**Full video tutorial:** \[YouTube Link Coming Soon\]
|
||||
|
||||
## What You Get
|
||||
|
||||
| Service | Port | Purpose |
|
||||
| --- | --- | --- |
|
||||
| Gluetun | — | VPN tunnel with kill switch |
|
||||
| qBittorrent | 8080 | Torrent client (VPN protected) |
|
||||
| Prowlarr | 9696 | Indexer manager (VPN protected) |
|
||||
| FlareSolverr | 8191 | Cloudflare bypass (VPN protected) |
|
||||
| Radarr | 7878 | Movie automation |
|
||||
| Sonarr | 8989 | TV show automation |
|
||||
| Lidarr | 8686 | Music automation |
|
||||
| Bazarr | 6767 | Subtitle automation |
|
||||
| Jellyfin | 8096 | Media server / streaming |
|
||||
| Seerr | 5055 | Netflix-like request UI (Overseerr/Jellyseerr successor) |
|
||||
|
||||
All download traffic routes through Gluetun's VPN tunnel. If the VPN drops, all traffic stops — zero leaks. The deunhealth container auto-restarts services that become unhealthy.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1\. Install Docker
|
||||
|
||||
```
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in for group change to take effect
|
||||
```
|
||||
|
||||
### 2\. Clone this repo
|
||||
|
||||
```
|
||||
git clone https://github.com/loponai/arrstack.git
|
||||
cd arrstack
|
||||
```
|
||||
|
||||
### 3\. Create folder structure
|
||||
|
||||
```
|
||||
sudo bash setup-folders.sh
|
||||
```
|
||||
|
||||
This creates:
|
||||
|
||||
```
|
||||
/data/
|
||||
├── torrents/ ← qBittorrent downloads here
|
||||
│ ├── movies/
|
||||
│ ├── tv/
|
||||
│ └── music/
|
||||
└── media/ ← Radarr/Sonarr organize files here (Jellyfin reads from here)
|
||||
├── movies/
|
||||
├── tv/
|
||||
└── music/
|
||||
```
|
||||
|
||||
> **Hard links:** Both folders MUST be on the same drive/filesystem. Radarr and Sonarr create hard links (not copies) — the file appears in both locations but only uses disk space once.
|
||||
|
||||
### 4\. Configure your VPN
|
||||
|
||||
```
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Fill in your VPN provider and credentials. See [VPN Setup Guides](#vpn-setup-guides) below.
|
||||
|
||||
### 5\. Launch
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 6\. Verify everything is working
|
||||
|
||||
```
|
||||
bash test-stack.sh
|
||||
```
|
||||
|
||||
This runs a full health check — Docker status, VPN connection, IP leak test, service accessibility, hard link support, and folder permissions. If anything is wrong, it tells you exactly what to fix.
|
||||
|
||||
You can also check manually:
|
||||
|
||||
```
|
||||
# Check Gluetun's IP (should be VPN, not your real IP)
|
||||
docker exec gluetun wget -qO- ifconfig.me
|
||||
|
||||
# qBittorrent shares Gluetun's network, so the above proves both are tunneled.
|
||||
docker exec qbittorrent wget -qO- ifconfig.me
|
||||
|
||||
# Check health status of all containers
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
### 7\. Configure services
|
||||
|
||||
Open each service in your browser at `http://YOUR-SERVER-IP:PORT` and follow the video tutorial for step-by-step configuration.
|
||||
|
||||
**Quick reference:**
|
||||
|
||||
- **qBittorrent** (`:8080`) — Get temp password: `docker logs qbittorrent 2>&1 | grep "temporary password"`
|
||||
- **Prowlarr** (`:9696`) — Add indexers, connect to Radarr/Sonarr. If an indexer is blocked by Cloudflare, set up FlareSolverr as a proxy: Settings → Indexers → Add Proxy → FlareSolverr → host `http://localhost:8191` → give it a tag (e.g. `flaresolverr`). Then edit the blocked indexer and add the **same tag** so Prowlarr routes it through FlareSolverr.
|
||||
- **Radarr** (`:7878`) — Root folder: `/data/media/movies`, download client category: `movies`
|
||||
- **Sonarr** (`:8989`) — Root folder: `/data/media/tv`, download client category: `tv`
|
||||
- **Jellyfin** (`:8096`) — Add libraries: `/data/media/movies`, `/data/media/tv`, `/data/media/music`. To watch, open `http://YOUR-SERVER-IP:8096` in a browser or use the Jellyfin app (available on Roku, Fire TV, Apple TV, Android TV, iOS, Android). Find your server IP by running `hostname -I` in the terminal. If watching remotely with Tailscale, use your Tailscale IP instead.
|
||||
- **Seerr** (`:5055`) — Connect to Jellyfin, Radarr, and Sonarr. Seerr is the unified successor to Overseerr/Jellyseerr. If you previously ran Jellyseerr here, your existing config is migrated automatically on first start.
|
||||
|
||||
**Internal Docker IPs — use these when connecting services to each other (NOT localhost):**
|
||||
|
||||
| IP | Service |
|
||||
| --- | --- |
|
||||
| `172.39.0.2` | Gluetun (also qBittorrent, Prowlarr, FlareSolverr) |
|
||||
| `172.39.0.3` | Radarr |
|
||||
| `172.39.0.4` | Sonarr |
|
||||
| `172.39.0.5` | Lidarr |
|
||||
| `172.39.0.6` | Bazarr |
|
||||
| `172.39.0.7` | Jellyfin |
|
||||
| `172.39.0.8` | Seerr |
|
||||
|
||||
These IPs are the same for everyone — they're hardcoded in the docker-compose file.
|
||||
|
||||
**Common connections:**
|
||||
|
||||
- Radarr/Sonarr → Download Client → qBittorrent: host `172.39.0.2`, port `8080`
|
||||
- Prowlarr → Apps → Radarr: server `http://172.39.0.3:7878`
|
||||
- Prowlarr → Apps → Sonarr: server `http://172.39.0.4:8989`
|
||||
- Prowlarr → Apps → Prowlarr Server: `http://172.39.0.2:9696`
|
||||
- Seerr → Radarr: host `172.39.0.3`, port `7878`
|
||||
- Seerr → Sonarr: host `172.39.0.4`, port `8989`
|
||||
- Seerr → Jellyfin: host `172.39.0.7`, port `8096`
|
||||
|
||||
**Important Radarr/Sonarr settings:**
|
||||
|
||||
- Media Management → Show Advanced → **Use Hardlinks instead of Copy** → must be ON
|
||||
- Media Management → **Rename Movies/Episodes** → recommended ON
|
||||
|
||||
**Recommended quality profile (1080p baseline, 4K preferred):**
|
||||
|
||||
Go to Settings → Profiles and edit or create a profile:
|
||||
|
||||
1. Uncheck everything below 1080p (720p, 480p, etc.)
|
||||
2. Check/enable everything from **HDTV-1080p** up through **Bluray-2160p**
|
||||
3. Set **Cutoff** to `Bluray-1080p` — this is the minimum quality Radarr/Sonarr will be happy with
|
||||
4. Set **Upgrade Until** to `Bluray-2160p` — it will automatically upgrade to 4K if one becomes available
|
||||
|
||||
This means it grabs a 1080p release right away so you can start watching, then silently upgrades to 4K later if it finds one.
|
||||
|
||||
## VPN Setup Guides
|
||||
|
||||
### Surfshark (Recommended)
|
||||
|
||||
The best value for torrenting — cheapest long-term plans, fast WireGuard speeds, and easy setup with Gluetun. [Get Surfshark](https://get.surfshark.net/aff_c?offer_id=1126&aff_id=9447&aff_sub=8amjxr)
|
||||
|
||||
1. Go to [Surfshark Manual Setup](https://my.surfshark.com/vpn/manual-setup/main)
|
||||
2. Select **WireGuard** and get your credentials (private key + address)
|
||||
3. In your `.env`:
|
||||
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=surfshark
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.14.0.2/16
|
||||
SERVER_COUNTRIES=United States
|
||||
```
|
||||
|
||||
> The `.env.example` file is pre-configured for Surfshark. Just paste your private key and you're good to go.
|
||||
|
||||
### NordVPN
|
||||
|
||||
1. Go to [NordVPN Manual Setup](https://my.nordaccount.com/dashboard/nordvpn/manual-configuration/)
|
||||
2. Select **NordLynx** (WireGuard) and generate a private key
|
||||
3. In your `.env`:
|
||||
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=nordvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.5.0.2/16
|
||||
SERVER_COUNTRIES=United States
|
||||
```
|
||||
|
||||
### ProtonVPN
|
||||
|
||||
1. Go to [ProtonVPN WireGuard Config](https://account.protonvpn.com/) → Downloads → WireGuard
|
||||
2. Generate a config file, open it, copy `PrivateKey` and `Address`
|
||||
3. In your `.env`:
|
||||
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=protonvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_ADDRESSES=10.2.0.2/32
|
||||
SERVER_COUNTRIES=United States
|
||||
VPN_PORT_FORWARDING=on
|
||||
```
|
||||
|
||||
### AirVPN
|
||||
|
||||
1. Go to [AirVPN Config Generator](https://airvpn.org/) → Client Area → Config Generator
|
||||
2. Select Linux → WireGuard → pick server → Generate
|
||||
3. In your `.env`:
|
||||
|
||||
```
|
||||
VPN_SERVICE_PROVIDER=airvpn
|
||||
VPN_TYPE=wireguard
|
||||
WIREGUARD_PRIVATE_KEY=your_key_here
|
||||
WIREGUARD_PUBLIC_KEY=server_public_key
|
||||
WIREGUARD_PRESHARED_KEY=your_preshared_key
|
||||
WIREGUARD_ADDRESSES=your_ip/32
|
||||
FIREWALL_VPN_INPUT_PORTS=your_port
|
||||
VPN_PORT_FORWARDING=on
|
||||
```
|
||||
|
||||
### Other Providers
|
||||
|
||||
Gluetun supports 30+ providers. Check the [full provider list](https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers).
|
||||
|
||||
## Starting and Stopping
|
||||
|
||||
**Start the stack:**
|
||||
|
||||
```
|
||||
cd arrstack
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Stop the stack:**
|
||||
|
||||
```
|
||||
cd arrstack
|
||||
docker compose down
|
||||
```
|
||||
|
||||
**Check status:**
|
||||
|
||||
```
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
### Auto-Start After Reboot
|
||||
|
||||
All containers are set to `restart: unless-stopped`, which means they automatically come back once Docker is running. You just need to make sure Docker itself starts when your computer boots up.
|
||||
|
||||
**Linux (dedicated server or VM):**
|
||||
|
||||
Run this once and you're done:
|
||||
|
||||
```
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
**Windows (running Docker inside WSL):**
|
||||
|
||||
WSL (Windows Subsystem for Linux) doesn't start Docker automatically when your PC boots. Here's how to fix that:
|
||||
|
||||
**Step 1:** Open your WSL terminal and run this command to edit the WSL config file:
|
||||
|
||||
```
|
||||
sudo nano /etc/wsl.conf
|
||||
```
|
||||
|
||||
**Step 2:** Your file might already have some lines in it (like `[boot]` or `[user]`). Look for a `[boot]` section. If it exists, add the `command=` line under it. If it doesn't exist, add both lines. It should look like this when you're done:
|
||||
|
||||
```
|
||||
[boot]
|
||||
command=service docker start
|
||||
```
|
||||
|
||||
**Step 3:** Save the file by pressing `Ctrl+X`, then `Y`, then `Enter`.
|
||||
|
||||
**Step 4 (optional):** By default, WSL only starts when you open a terminal. If you want it to start automatically when Windows boots (so your stack is always running), do this:
|
||||
|
||||
1. Press `Win+R` on your keyboard
|
||||
2. Type `shell:startup` and press Enter — this opens your Windows Startup folder
|
||||
3. Right-click in the folder → New → Text Document
|
||||
4. Name it `wsl.vbs` (make sure it ends in `.vbs`, not `.vbs.txt` — if you can't see file extensions, go to View → Show → File name extensions in File Explorer)
|
||||
5. Right-click the file → Edit (or Open with Notepad) and paste this:
|
||||
```
|
||||
Set ws = CreateObject("Wscript.Shell")
|
||||
ws.Run "wsl -d Ubuntu -u root -- service docker start", 0
|
||||
```
|
||||
6. Save and close
|
||||
|
||||
That's it — next time your PC restarts, WSL starts Docker automatically and all your containers come back up on their own. No commands needed.
|
||||
|
||||
## Updating
|
||||
|
||||
```
|
||||
cd arrstack
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Remote Access with Tailscale (Optional)
|
||||
|
||||
Want to access Jellyfin, Seerr, or any service from outside your home? [Tailscale](https://tailscale.com/) creates a private network between your devices — no port forwarding, no exposing anything to the public internet.
|
||||
|
||||
**On your server:**
|
||||
|
||||
```
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
sudo tailscale up
|
||||
```
|
||||
|
||||
**On your phone/laptop/TV:**
|
||||
|
||||
1. Install Tailscale from your app store
|
||||
2. Sign in with the same account
|
||||
|
||||
**Access your services from anywhere:**
|
||||
|
||||
```
|
||||
http://YOUR-TAILSCALE-IP:8096 ← Jellyfin
|
||||
http://YOUR-TAILSCALE-IP:5055 ← Seerr
|
||||
http://YOUR-TAILSCALE-IP:7878 ← Radarr
|
||||
http://YOUR-TAILSCALE-IP:8989 ← Sonarr
|
||||
```
|
||||
|
||||
Find your Tailscale IP with `tailscale ip -4` on the server.
|
||||
|
||||
Tailscale is free for personal use (up to 100 devices). Everything is encrypted with WireGuard — nobody can see your traffic, not even Tailscale.
|
||||
|
||||
> **Do NOT expose Jellyfin directly to the internet** (no port forwarding on your router). Use Tailscale or a reverse proxy instead. Direct exposure is a security risk.
|
||||
|
||||
### Sharing with Family and Friends
|
||||
|
||||
Your family and friends only need two things — **Seerr** to request movies/shows and **Jellyfin** to watch them. They never see Radarr, Sonarr, qBittorrent, or any of the behind-the-scenes stuff.
|
||||
|
||||
**Step 1: Invite them to your Tailscale network**
|
||||
|
||||
1. Go to the [Tailscale admin console](https://login.tailscale.com/admin/machines)
|
||||
2. Click **Share** on your server's machine
|
||||
3. Enter their email — they'll get an invite link
|
||||
|
||||
**Step 2: They install Tailscale**
|
||||
|
||||
1. Download Tailscale on their phone, laptop, or TV from [tailscale.com/download](https://tailscale.com/download)
|
||||
2. Accept your invite and sign in
|
||||
|
||||
**Step 3: They access your services**
|
||||
|
||||
Give them these two links (replace with your Tailscale IP):
|
||||
|
||||
```
|
||||
http://YOUR-TAILSCALE-IP:5055 ← Seerr (request movies and shows)
|
||||
http://YOUR-TAILSCALE-IP:8096 ← Jellyfin (watch everything)
|
||||
```
|
||||
|
||||
**For TVs and phones**, they can install the **Jellyfin app** (available on Roku, Fire TV, Apple TV, Android TV, iOS, Android) and enter your Tailscale IP as the server address during setup.
|
||||
|
||||
That's it — they request, you automatically download, they watch. No technical knowledge needed on their end.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Gluetun unhealthy / won't connect:**
|
||||
|
||||
- Double-check VPN credentials in `.env` — these are NOT your login email/password
|
||||
- Try removing the gluetun folder and restarting: `rm -rf gluetun && docker compose up -d`
|
||||
- Check logs: `docker logs gluetun`
|
||||
|
||||
**qBittorrent can't connect:**
|
||||
|
||||
- Make sure Gluetun is healthy: `docker ps` (should show "healthy")
|
||||
- Check qBit is using VPN: `docker exec gluetun wget -qO- ifconfig.me`
|
||||
- In qBittorrent settings → Advanced → set Network Interface to `tun0`
|
||||
|
||||
**Movie or show not downloading:**
|
||||
|
||||
- **Quality profile too strict** — If Radarr/Sonarr can't find a release matching your quality profile, it won't download anything. Go to the movie/show → check if it says "No results found" or similar. Try lowering your cutoff temporarily (e.g. from Bluray-1080p to WEBDL-1080p) or enabling more quality tiers in your profile.
|
||||
- **Not enough indexers** — Public indexers have limited catalogs. If you only have one or two indexers in Prowlarr, add more (1337x, The Pirate Bay, LimeTorrents, EZTV). The more indexers you have, the more results you'll get.
|
||||
- **Not enough seeders** — Some torrents just don't have anyone sharing them, especially older or niche content. Check qBittorrent — if the torrent is stuck at 0% with 0 seeds, there's nothing to download. Try searching manually in Radarr/Sonarr for a different release with more seeders.
|
||||
- **Indexer blocked by Cloudflare** — See the Prowlarr setup note above about setting up FlareSolverr with tags.
|
||||
|
||||
**Hard links not working (files copying instead):**
|
||||
|
||||
- Both `/data/torrents` and `/data/media` must be on the same filesystem
|
||||
- Check Radarr/Sonarr → Settings → Media Management → "Use Hardlinks" is checked
|
||||
- Verify with: `ls -i /data/torrents/movies/yourfile` and `ls -i /data/media/movies/YourMovie/yourfile` — inode numbers should match
|
||||
|
||||
**Permission errors:**
|
||||
|
||||
- Run `id` and make sure PUID/PGID in `.env` match your user
|
||||
- Re-run: `sudo chown -R $(id -u):$(id -g) /data`
|
||||
|
||||
**Service won't start — "port already in use":**
|
||||
|
||||
Another program on your system might be using the same port. This is common with port 5055 (Seerr) but can happen with any service.
|
||||
|
||||
1. Find what's using the port (replace `5055` with the port number from the error):
|
||||
**Linux:**
|
||||
```
|
||||
sudo ss -tlnp | grep 5055
|
||||
```
|
||||
**Windows (WSL users) — run in PowerShell:**
|
||||
```
|
||||
netstat -ano | findstr :5055
|
||||
```
|
||||
This gives you a PID (process ID). Find the program name:
|
||||
```
|
||||
Get-Process -Id <PID> | Select-Object ProcessName, Id, Path
|
||||
```
|
||||
2. Either stop/disable that program, or change the port in `docker-compose.yml` to an unused one (e.g. `5056:5055`).
|
||||
3. If it's a Windows service hogging the port, disable it in an admin PowerShell:
|
||||
```
|
||||
Stop-Service <ServiceName> -Force
|
||||
Set-Service <ServiceName> -StartupType Disabled
|
||||
```
|
||||
4. Then recreate the container:
|
||||
```
|
||||
docker compose up -d --force-recreate <service-name>
|
||||
```
|
||||
|
||||
**Seerr stuck restarting / crash-looping:**
|
||||
|
||||
The current `docker-compose.yml` uses a named volume (`seerr_config`) for Seerr's config, which fixes both causes of the crash loop. If you're still hitting it, you're almost certainly on an older version of this repo that used a bind mount. `git pull` first.
|
||||
|
||||
Root cause (for reference):
|
||||
|
||||
- **Linux/macOS:** Seerr runs as the `node` user (UID 1000). A bind-mounted `./seerr` folder is created root-owned on first `docker compose up`, so the container can't write to `/app/config` and crash-loops. Upstream Seerr docs require `chown -R 1000:1000` on the config dir before first start.
|
||||
- **Windows/WSL:** Bind mounts go through an SMB share inside Docker Desktop's VM, which doesn't support file locking. Seerr's SQLite DB corrupts on first write. Upstream Seerr docs explicitly say: **do not bind-mount `/app/config` on Windows** — use a named volume.
|
||||
|
||||
Named volumes sidestep both problems because Docker creates them with correct ownership inside its own managed storage.
|
||||
|
||||
If you still see it after pulling:
|
||||
|
||||
- Check logs: `docker logs seerr | tail -30`
|
||||
- Nuke the volume and start fresh (you'll lose Seerr settings, not media):
|
||||
```
|
||||
docker compose down seerr && docker volume rm arrstack_seerr_config && docker compose up -d seerr
|
||||
```
|
||||
|
||||
**Migrating Seerr config to a named volume (existing installs):**
|
||||
|
||||
If you had Seerr working on an older version of this repo with a bind-mounted `./jellyseerr` or `./seerr` folder and want to keep your settings, copy the data into the new named volume before starting:
|
||||
|
||||
```
|
||||
docker compose down seerr
|
||||
# pick whichever folder you actually have
|
||||
SRC=./seerr
|
||||
[ -d ./jellyseerr ] && SRC=./jellyseerr
|
||||
docker volume create arrstack_seerr_config
|
||||
docker run --rm -v "$(pwd)/${SRC#./}":/src -v arrstack_seerr_config:/dest alpine sh -c "cp -a /src/. /dest/ && chown -R 1000:1000 /dest"
|
||||
docker compose up -d seerr
|
||||
```
|
||||
|
||||
If you don't care about preserving settings, just `docker compose up -d seerr` — Seerr will start fresh and walk you through setup again.
|
||||
|
||||
**Can't log into qBittorrent:**
|
||||
|
||||
- qBittorrent generates a temporary password every time it starts. Get it with:
|
||||
```
|
||||
docker logs qbittorrent 2>&1 | grep "temporary password"
|
||||
```
|
||||
- Default username is `admin`. Once logged in, go to Tools → Options → Web UI and set a permanent password.
|
||||
|
||||
**Services can't connect to each other (connection refused, timeout):**
|
||||
|
||||
- Don't use `localhost` when connecting services together — that won't work across Docker containers.
|
||||
- Use the internal Docker IPs instead:
|
||||
- qBittorrent/Prowlarr/FlareSolverr: `172.39.0.2`
|
||||
- Radarr: `172.39.0.3`
|
||||
- Sonarr: `172.39.0.4`
|
||||
- Jellyfin: `172.39.0.7`
|
||||
- The one exception: Prowlarr → FlareSolverr can use `localhost:8191` because they both run through Gluetun and share the same network.
|
||||
|
||||
**"Root folder does not exist" in Radarr/Sonarr:**
|
||||
|
||||
- Make sure you ran `sudo bash setup-folders.sh` to create the `/data` directory structure.
|
||||
- Double-check the root folder path — it should be `/data/media/movies` for Radarr and `/data/media/tv` for Sonarr (not `/movies` or `/data/movies`).
|
||||
|
||||
**Downloads stuck at "importing" or "waiting to import":**
|
||||
|
||||
- This is almost always a permissions issue. Fix it with:
|
||||
```
|
||||
sudo chown -R $(id -u):$(id -g) /data
|
||||
sudo chmod -R 775 /data
|
||||
```
|
||||
- Make sure PUID/PGID in your `.env` match your user (check with `id`).
|
||||
|
||||
**Jellyfin library is empty after downloads finish:**
|
||||
|
||||
- Make sure your Jellyfin libraries point to the correct paths: `/data/media/movies`, `/data/media/tv`, `/data/media/music`
|
||||
- Jellyfin doesn't scan instantly. Go to Dashboard → Libraries → click the `...` menu → **Scan Library** to force a refresh.
|
||||
- You can also set up scheduled scans in Dashboard → Scheduled Tasks.
|
||||
|
||||
**Subtitles not downloading (Bazarr):**
|
||||
|
||||
- Bazarr needs to be connected to Radarr and Sonarr: Settings → Radarr / Sonarr → enter the IP (`172.39.0.3` / `172.39.0.4`) and API key.
|
||||
- You also need at least one subtitle provider: Settings → Providers → Add → **OpenSubtitles.com** is the most popular (free account required).
|
||||
|
||||
**Everything works but downloads are slow:**
|
||||
|
||||
- Your VPN server might be too far away. Change `SERVER_COUNTRIES` in your `.env` to a country closer to you, then restart:
|
||||
```
|
||||
docker compose down && docker compose up -d
|
||||
```
|
||||
- Check your VPN speed: `docker exec gluetun wget -qO- https://speed.cloudflare.com/__down?measId=10000000 > /dev/null` — if it's very slow, try a different country.
|
||||
|
||||
**Disk space filling up:**
|
||||
|
||||
- By default, qBittorrent keeps torrents after Radarr/Sonarr imports them. To auto-clean:
|
||||
- In Radarr/Sonarr → Settings → Download Clients → click on qBittorrent → enable **Remove Completed**
|
||||
- This deletes the torrent from qBittorrent after the file has been imported (the hard link in your media folder is kept, so you don't lose anything).
|
||||
|
||||
**VPN IP leak — want to make sure your real IP isn't exposed:**
|
||||
|
||||
```
|
||||
# Check the VPN container's IP (should NOT be your real IP)
|
||||
docker exec gluetun wget -qO- ifconfig.me
|
||||
|
||||
# Compare with your real IP (run this outside Docker)
|
||||
curl -s ifconfig.me
|
||||
```
|
||||
|
||||
If both IPs are the same, your VPN isn't working — check Gluetun logs with `docker logs gluetun`.
|
||||
|
||||
## Credits
|
||||
|
||||
Built by [Tom Spark](https://youtube.com/@tomspark) following [Trash Guides](https://trash-guides.info/) and [Servarr Wiki](https://wiki.servarr.com/) best practices.
|
||||
|
||||
Uses [Gluetun](https://github.com/qdm12/gluetun) for VPN, [LinuxServer.io](https://linuxserver.io/) container images, and [Seerr](https://github.com/seerr-team/seerr) for the request system (the unified successor to Overseerr/Jellyseerr).
|
||||
@@ -0,0 +1,135 @@
|
||||
```
|
||||
# ============================================================
|
||||
# Tom Spark's ARR Stack — Environment Configuration
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# INSTRUCTIONS:
|
||||
# 1. Copy this file: cp .env.example .env
|
||||
# 2. Fill in your VPN credentials below
|
||||
# 3. Adjust timezone and user IDs if needed
|
||||
# 4. Run: docker compose up -d
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# SYSTEM SETTINGS
|
||||
# ============================================================
|
||||
|
||||
# Your timezone (list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
|
||||
TZ=America/New_York
|
||||
|
||||
# Your Linux user/group ID. Find yours with: id
|
||||
# Most systems default to 1000. If yours is different, change these.
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
|
||||
# ============================================================
|
||||
# VPN SETTINGS — Pick your provider and fill in credentials
|
||||
# Full provider list: https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers
|
||||
#
|
||||
# IMPORTANT: VPN credentials are NOT your login email/password!
|
||||
# You need service credentials from your VPN provider's manual
|
||||
# setup or API section. See the provider examples at the bottom of this file.
|
||||
# ============================================================
|
||||
|
||||
# Your VPN provider (surfshark, nordvpn, protonvpn, airvpn, mullvad, private internet access, windscribe, etc.)
|
||||
VPN_SERVICE_PROVIDER=airvpn
|
||||
|
||||
# Protocol: wireguard (recommended, faster) or openvpn
|
||||
VPN_TYPE=wireguard
|
||||
|
||||
# --- WIREGUARD CREDENTIALS ---
|
||||
# For Surfshark: go to https://my.surfshark.com/vpn/manual-setup/main → WireGuard
|
||||
# For other providers: see the examples at the bottom of this file
|
||||
WIREGUARD_PRIVATE_KEY=eDgf3GPFy2ltgx2RkD/Vx5wKZ4dVi28YbQmSJOrbWmk=
|
||||
WIREGUARD_ADDRESSES=10.175.23.30
|
||||
# Only needed for some providers (AirVPN). Leave blank if not required.
|
||||
WIREGUARD_PUBLIC_KEY=
|
||||
WIREGUARD_PRESHARED_KEY=+0+hrSdzRUxKDNk1Q37PNmNJ2jsj2EzF45JtbZad4lI=
|
||||
|
||||
# --- OPENVPN CREDENTIALS ---
|
||||
# Only needed if VPN_TYPE=openvpn. Leave blank if using WireGuard.
|
||||
OPENVPN_USER=
|
||||
OPENVPN_PASSWORD=
|
||||
|
||||
# --- SERVER SELECTION ---
|
||||
# Pick a country close to you for best speeds
|
||||
SERVER_COUNTRIES=Canada
|
||||
|
||||
# --- PORT FORWARDING ---
|
||||
# Supported by: ProtonVPN, AirVPN, PIA. Can help with upload speeds and seeding.
|
||||
# Not required for downloading. Most users don't need this.
|
||||
# Set to "on" if your provider supports it, leave blank otherwise (Surfshark, NordVPN, etc.).
|
||||
VPN_PORT_FORWARDING=
|
||||
# If your provider requires manually specifying a port (e.g. AirVPN):
|
||||
FIREWALL_VPN_INPUT_PORTS=29261
|
||||
# ============================================================
|
||||
# NETWORK — Static IPs for each service
|
||||
# You shouldn't need to change these unless you have a conflict.
|
||||
# ============================================================
|
||||
IP_GLUETUN=172.39.0.2
|
||||
IP_RADARR=172.39.0.3
|
||||
IP_SONARR=172.39.0.4
|
||||
IP_LIDARR=172.39.0.5
|
||||
IP_BAZARR=172.39.0.6
|
||||
IP_JELLYFIN=172.39.0.7
|
||||
IP_SEERR=172.39.0.8
|
||||
IP_AUDIO=172.39.0.9
|
||||
IP_NAVI=172.39.0.10
|
||||
|
||||
# ============================================================
|
||||
# PROVIDER-SPECIFIC EXAMPLES
|
||||
# Uncomment and fill in the section for your VPN provider.
|
||||
# ============================================================
|
||||
|
||||
# --- NORDVPN ---
|
||||
# 1. Go to: https://my.nordaccount.com/dashboard/nordvpn/manual-configuration/
|
||||
# 2. Generate a WireGuard private key (NordLynx)
|
||||
# 3. Paste the private key below
|
||||
# VPN_SERVICE_PROVIDER=nordvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_nordvpn_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.5.0.2/16
|
||||
# SERVER_COUNTRIES=United States
|
||||
|
||||
# --- PROTONVPN ---
|
||||
# 1. Go to: https://account.protonvpn.com/ → Downloads → WireGuard configuration
|
||||
# 2. Generate a config, open the file, copy the PrivateKey and Address
|
||||
# 3. Port forwarding is supported on paid plans
|
||||
# VPN_SERVICE_PROVIDER=protonvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_proton_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.2.0.2/32
|
||||
# SERVER_COUNTRIES=United States
|
||||
# VPN_PORT_FORWARDING=on
|
||||
|
||||
# --- SURFSHARK ---
|
||||
# 1. Go to: https://my.surfshark.com/vpn/manual-setup/main
|
||||
# 2. Get WireGuard credentials
|
||||
# VPN_SERVICE_PROVIDER=surfshark
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_surfshark_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.14.0.2/16
|
||||
# SERVER_COUNTRIES=United States
|
||||
|
||||
# --- AIRVPN ---
|
||||
# 1. Go to: https://airvpn.org/ → Client Area → Config Generator
|
||||
# 2. Select Linux → WireGuard → pick a server → Generate
|
||||
# 3. Copy all keys and the assigned IP
|
||||
# VPN_SERVICE_PROVIDER=airvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_airvpn_private_key_here
|
||||
# WIREGUARD_PUBLIC_KEY=your_airvpn_public_key_here
|
||||
# WIREGUARD_PRESHARED_KEY=your_airvpn_preshared_key_here
|
||||
# WIREGUARD_ADDRESSES=your_assigned_ip/32
|
||||
# FIREWALL_VPN_INPUT_PORTS=your_forwarded_port
|
||||
# VPN_PORT_FORWARDING=on
|
||||
|
||||
# --- MULLVAD ---
|
||||
# 1. Go to: https://mullvad.net/en/account → WireGuard configuration
|
||||
# VPN_SERVICE_PROVIDER=mullvad
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_mullvad_private_key_here
|
||||
# WIREGUARD_ADDRESSES=your_assigned_ip/32
|
||||
# SERVER_COUNTRIES=United States
|
||||
|
||||
```
|
||||
+306
@@ -0,0 +1,306 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- ansible
|
||||
---
|
||||
|
||||
|
||||
With our continuing efforts in building an MSP on open source it's important to realize we will need tools to help us automate many of the day to day operations we'll be performing for our clients as well as on our own systems. This brings us to Ansible.
|
||||
|
||||
Ansible is an incredibly powerful and robust tool made specifically for automating workflows and actions. It works on Linux, MacOS, and Windows, and can help reduce your task load by thousands, or even tens of thousands of individual actions. We will be rolling out Ansible during our series on building an MSP as a tool to help us deal with a growing business where we are supporting our clients and their multitudes of devices. We will employ Ansible's power to push out updates, agents for the various software services we'll employ, and so much more.
|
||||
|
||||
This is just an introduction to ansible, and will get you started with it, but it is highly recommended that you also check out other series on ansible. I'll link to one below that will take you a bit deeper. You should, of course start getting comfortable with the ansible documentation. This is one of the most well documented tools in the open source world. The answers are there for you, just waiting to be read and put to use.
|
||||
|
||||
### What You'll Need
|
||||
|
||||
* A machine to use as an Ansible controller (the server that you run Ansible commands from).
|
||||
* An SSH Public / Private key pair
|
||||
* SSH Access to any target machine (client machine)
|
||||
* About thirty minutes of your time
|
||||
|
||||
### SSH Key Pair Setup
|
||||
|
||||
For this series, I'll be installing Ansible itself on a Ubuntu 22.04 LTS Incus (LXD) container. This is a dedicated virtual machine I'm creating for the sole purpose of running Ansible. You can do the same, or use your main laptop or desktop machine. Keep in mind, that as we grow our use of Ansible, we will want to start scheduling certain tasks to run, so we'll want a machine that is always on and ready.
|
||||
|
||||
To setup an SSH key pair, we can run the following command:
|
||||
|
||||
`ssh-keygen -t ed25519 -C "ansible"`
|
||||
|
||||
The command above tells ssh to generate a key pair using the ed25519 encryption. This encryption is similar in strength to RSA 256, but is a much shorter key, and uses less computer power to generate.
|
||||
|
||||
When you submit the command, you'll be prompted on where to store the command, and what to call it. This is up to you, but I highly recommend, you keep the key pair in
|
||||
|
||||
`/home/<your user>/.ssh/`
|
||||
|
||||
as this is where OpenSSH looks for the keys automatically. As for the name, name it something that makes sense for it's purpose. In my case I will name it 'ansible'. So my entier path and name will look like
|
||||
|
||||
`/home/<your user>/.ssh/ansible`
|
||||
|
||||
Next, you'll be prompted for a passphrase for this key. We want to leave this blank so that we won't be prompted each time for our passphrase as ansible goes to login to the machines it's taking action on.
|
||||
|
||||
Just press Enter to keep the passphrase blank. Next, confirm that you want it blank (empy) by simply pressing Enter again.
|
||||
|
||||
SSH will now generate a secure public and private key pair for you. If you do an `ls` on this folder ( /home/<your user>/.ssh ) you'll see that two new files haave been added. They'll be called `ansible` and `ansible.pub`. The file ending in .pub is your public key file and can be shared out to all of the machines you want to access with ansible. the other file is your private key file and should never be shared with anyone, nor sent to public machines. The `ansible` file is your key to access any host with the `ansible.pub` file on it.
|
||||
|
||||
### Send Our New Key to Target Machines
|
||||
|
||||
In order for ansible to run, we need to share our new key to target machines. We can do this wil the command
|
||||
|
||||
`ssh-copy-id`
|
||||
|
||||
This command allows us to specify which key to share, and to which host and for which user we share it.
|
||||
|
||||
I'll be adding 3 hosts to start, but it's not required. You can do just one if you prefer. My hosts will have the IPs
|
||||
|
||||
192.168.10.20, 192.168.10.21, and 192.168.10.22
|
||||
|
||||
Don't worry, your hosts don't have to have consecutive IP addresses.
|
||||
|
||||
Let's copy and SSH key over to the first host machine.
|
||||
|
||||
`ssh-copy-id -i /home/brian/.ssh/ansible` [`brian@192.168.10.20`](mailto:brian@192.168.10.20)
|
||||
|
||||
`-i` tells ssh that we are going to specify the file to send. We then tell it the path and key to send. You may notice I just put 'ansible' and not 'ansible.pub'. This is ok, as the `ssh-copy-id` command knows to send the public key, not the private key.
|
||||
|
||||
We press enter, then will be prompted for our password to access this machine via SSH. Enter the password, and you should get a message confirming that 1 key has been copied.
|
||||
|
||||
You can not attempt to access the machine using the new key with the ssh command as follows:
|
||||
|
||||
`ssh -i /home/brian/.ssh/ansible <a href="mailto:brian@192.168.10.20">brian@192.168.10.20</a>`
|
||||
|
||||
You should be logged onto the machine without being prompted for any password.
|
||||
|
||||
You have now copied your ssh key to another machine. Repeat the above process for however many machines you want to have ansible accessing.
|
||||
|
||||
### Install Ansible
|
||||
|
||||
Ansible is already packaged in most distribution repositories, but the Ubuntu 22.04 version lags behind a bit, so let's make sure we get the latest version possible. To do this, we'll add the ansible ppa repository instead.
|
||||
|
||||
`sudo add-apt-repository ppa:ansible/ansible`
|
||||
|
||||
When you submit the above command, you'll be prompted to press Enter, so press Enter, then you should see your system attempt to update the package cache. Let's runt he update one more time just to be sure.
|
||||
|
||||
`sudo apt update -y`
|
||||
|
||||
Now we can install the latest version of ansible with
|
||||
|
||||
`sudo apt install ansible -y`
|
||||
|
||||
### Creating an Ansible Inventory
|
||||
|
||||
Ansible uses an inventory file to know what machines you want it to access and perform actions on. This file can be yaml or plain text. We'll be starting with the plain text file for now, as I think it's a little bit easier to grasp initially. Feel free, however, to check out the documentation if you are a yaml expert.
|
||||
|
||||
Let's make our new file with
|
||||
|
||||
`nano inventory`
|
||||
|
||||
Note that Ansible can deal with machines collected into groups, and that a machine can be in more than one group, and that you can even group other groups as well.
|
||||
|
||||
We'll start with two groups for our example, but use whatever groups make sense for your needs. The organization for our inventory file will be like the following:
|
||||
|
||||
```
|
||||
[group_name]
|
||||
machine_alias_1 ansible_host=<machine_ip_1>
|
||||
machine_alias_2 ansible_host=<machine_ip_2>
|
||||
|
||||
[group_name_2]
|
||||
machine_alias_3 ansible_host=<machine_ip_3>
|
||||
```
|
||||
|
||||
The items in square brackets are the group names we assign, and then below any group name we list the machines that are part of that gorup. We list the machines with an alias name, any name that describes what machine it is. This can be the machine hostname, or just an alias we want for the machine. After the alias, we put a space, then indicate the machines ip or fqdn for ansible to connect to the machine with. We identify it with the key `ansible_host=` then enter the ip or fqdn for the machine. Let's look at an actual example of our inventory file now.
|
||||
|
||||
```
|
||||
[home_server]
|
||||
dashy ansible_host=192.168.10.20
|
||||
vaultwarden ansible_host=192.168.10.21
|
||||
|
||||
[home_desktops]
|
||||
brian_studio ansible_host=192.168.10.22
|
||||
```
|
||||
|
||||
Above, you'll see two groups home\_server, and home\_desktops. The home\_server group has two machines in it, and one machine is held under the home\_desktops group.
|
||||
|
||||
NOTE: Ansible doesn't allow spaces in group names or aliases, nor hyphens ( - ), so you need to use underscores ( \\\_ ) in names where you want to separate words.
|
||||
|
||||
We can save our 'inventory' file with CTRL + O, then press Enter to confirm, and exit the nano editor with CTRL + X.
|
||||
|
||||
### Create an Ansible Playbook
|
||||
|
||||
Playbooks, are pretty much exactly what they sound like. They are the instructions that you want ansible to execute on a target machine, or set of machines. You can target individual machines (by alias), or group(s) of machines, and even the entire inventory if you want.
|
||||
|
||||
Playbooks are written in yaml (yes, the space dependent, very picky file format), but it does make plays easier to read, and as you get more accustomed to yaml, easier to update and modify as needed.
|
||||
|
||||
While stiill in our ansible\_projects folder, we'll create a new file called update\_ubuntu\_servers.yml.
|
||||
|
||||
`nano update_ubuntu_server.yml`
|
||||
|
||||
This will hold the plays we need in order to update our servers and desktops that are running Ubuntu as a base operating system.
|
||||
|
||||
In the file, we'll start by stating which target machines from our inventory file we want to perform an update on.
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: all
|
||||
```
|
||||
|
||||
In the above file, we start with three hyphens on the first line to indicate the beginning of our yaml file. below that we tell ansible that we want to run this on all hosts in our inventory file. Now, if you have machines with differing operating systems, you could group them by OS, but there are some smart checks we can do to make sure we don't try to do `apt updte` on an OpenSuse, Redhat, or other non-apt system as well.
|
||||
|
||||
To run the updates in apt, we need to be a sudo user. In ansible this uses the 'become' parameter, so let's add that to our file.
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
```
|
||||
|
||||
It's 'become' as in "become super user" or root.
|
||||
|
||||
Now that we've got the initial portion set, we can start creating 'tasks' for ansible to perform on these systems. The first task is to update the package cache, and the next task is to run the update on any packages that need it, although we list them in the reverse order in the yaml file.
|
||||
|
||||
```
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
|
||||
- name: Update packages on Ubuntu systems
|
||||
become: true
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
||||
```
|
||||
|
||||
Given our additions above, we can see that we give the task a name, this helps us know what task is being performed. This can be any string really, so call the task whatever makes sense.
|
||||
|
||||
Next, we again tell it this needs to be done as a super user with `become: true`.
|
||||
|
||||
And finally, we add the 'apt' module, and give it two actions to complete. `upgrade`, and we define that we want it to do a distribution level upgrade with `upgrade: dist`. Next we tell it that it needs to update the cahce of packages with `update_cache: yes`.
|
||||
|
||||
We can save this file and run it as is, and presuming you've setup your target machines properly, it will indeed update the cache of packages, and then run the upgrade procedure.
|
||||
|
||||
But, what about kernel updates? This usually includes the need for a reboot as well. I think we should go ahead and include that as part of our instruction set. to do that we just add another `-name` block under our `tasks:` section.
|
||||
|
||||
First, let's have Ansible check to see if a reboot is required.
|
||||
|
||||
```
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
|
||||
- name: Update packages on Ubuntu systems
|
||||
become: true
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
||||
|
||||
- name: Check if a reboot is needed
|
||||
become: true
|
||||
stat:
|
||||
path: /var/run/reboot-required
|
||||
register: reboot_required
|
||||
```
|
||||
|
||||
In our next task section, we give it a descriptive name so we'll know what we've asked ansible to do. Then, again, we tell it to do this task as a super user. Next, we call the `stat` module. This can pull status information for us. We tell the 'stat' module to look in `/var/run/reboot-required` with the `path:` line, and finally we save the information in a variable with `register: reboot_required`. The variable name is 'reboot\_required', and the stat command will check to see if that path exists or not.
|
||||
|
||||
Now that we know if a reboot is required, let's tell Ansible to perform the reboot if the variable 'reboot\_required' is set to 'true' or 'yes'. To do that, we add another `-name:` section under our `tasks:` in our yaml file.
|
||||
|
||||
```
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
- name: Update packages on Ubuntu systems
|
||||
become: true
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
||||
|
||||
- name: Check if a reboot is needed
|
||||
become: true
|
||||
stat:
|
||||
path: /var/run/reboot-required
|
||||
register: reboot_required
|
||||
|
||||
- name: Rebooting Machine After Upgrade
|
||||
become: true
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 120
|
||||
when: reboot_required.stat.exists
|
||||
```
|
||||
|
||||
Here, we name our task 'Rebooting Machine After Upgrade', then tell Ansible it must be run with super user privileges, and finally call on the built in Ansible module to reboot a machine, `ansible.builtin.reboot`.
|
||||
|
||||
Below that we add a short waiting time of 120 seconds (2 minutes). This just gives the upgrade time to fully complete before the reboot. Finally, we tell Ansible to only do this reboot when our 'reboot\_required' variable shows that the `reboot-required` path exists. The `when` in Ansible is a nice easy way to add some logic to a task.
|
||||
|
||||
For example, if your friend asked, "Can you feed my dog?" That's pretyy open ended, and you may not want to feed their dog forever. So it's better for your friend to say, "Can you feed my dog _when_ I go on vacation next month?". Now your friend has put a qualifier on when you should feed the dog.
|
||||
|
||||
This is the same as in Ansible. We are saying, "when /var/run/reboot-required exists, wait 2 minutes, then reboot the machine." Otherwise no reboot is necessary, so we leave the machine running.
|
||||
|
||||
Now we are ready to save our file, and exit the nano editor. We will run this with the `ansible-playbook` command. With the command we want to give Ansible instruction to use our 'ansible' private key, and tell it which host(s) to run the play on. Since we put the 'when' clause in our play, we can, of course just tell it 'all', but later on that may be a bit inefficient.
|
||||
|
||||
`ansible-playbook --key-file ~/.ssh/ansible_key -i inventory --ask-become-pass update_ubuntu_server.yml`
|
||||
|
||||
When you press Enter, you'll see Ansible ask you for your super user password, this is the password on the remote machines, and if entered incorrectly, will generate a list of failed task attempts. Next, Ansible will ensure it can reach each target machine, then it will begin running through each task in the playbook. At the end you'll get a summary of whether a play succeeded or failed, how many changes were made, how many tasks were skipped, and so on. What we are looking for is no tasks skipped, and no tasks failed.
|
||||
|
||||
Once we have that result, we have a play we can now use anytime we want in order to keep all of our servers up to date. We can even set this up to run as a cron job, but we need a secure way to feed Ansible our super user password for the tasks that require super user privileges.
|
||||
|
||||
### Avoiding Fails on Different OSes
|
||||
|
||||
We can avoid fails that occur from running plays on machines or operating systems that don't make sense. Such as running apt on a Fedora machine. Again, we can turn to the 'when' operator in Ansible playbooks. The step where Ansible "gathers facts" is an important one, as Ansible grabs a bunch of details about our various machines. We can then use this information to create conditions
|
||||
|
||||
`when: ansible_distribution == 'Ubuntu'`
|
||||
|
||||
and
|
||||
|
||||
`when: ansible_distribution == 'Fedora'`
|
||||
|
||||
We can add this to our existing playbook, and add a section to update Fedora as well.
|
||||
|
||||
```
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
tasks:
|
||||
- name: Update packages on Ubuntu systems
|
||||
become: true
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
|
||||
- name: Update packages on Fedora systems
|
||||
become: true
|
||||
dnf:
|
||||
update_only: true
|
||||
update_cache: true
|
||||
when: ansible_distribution == 'Fedora'
|
||||
|
||||
- name: Check if a reboot is needed
|
||||
become: true
|
||||
stat:
|
||||
path: /var/run/reboot-required
|
||||
register: reboot_required
|
||||
|
||||
- name: Rebooting Machine After Upgrade
|
||||
become: true
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 120
|
||||
when: reboot_required.stat.exists
|
||||
```
|
||||
|
||||
In the above, we've added a new task named 'Update packages on Fedora systems', and instead of 'apt', we use 'dnf' as this is the package manager for Fedora, CentOS, Red Hat, etc.
|
||||
|
||||
Finally, we added a 'when' clause to the Ubuntu update task, and one to the Fedora update task. This clause will ensure that these tasks only attempt to update systems where the distribution matches the package manager we are using.
|
||||
|
||||
You're now setup with a great base for using Ansible to get things built out for automated management of systems and packages. We'll be using this in future videos in this series, so dig in, start watching and reading, and get comfortable with Ansible.
|
||||
|
||||
Series for learning Ansible that I suggest:
|
||||
|
||||
### Support My Channel and Content
|
||||
|
||||
**Support my Channel and ongoing efforts through Patreon:**
|
||||
[patreon.com/awesomeopensource](https://patreon.com/awesomeopensource "Awesome Open Source Patreon Page")
|
||||
|
||||
**Buy me a Beer / Coffee:**
|
||||
[https://paypal.me/BrianMcGonagill](https://paypal.me/BrianMcGonagill)
|
||||
@@ -0,0 +1,463 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
---
|
||||
|
||||
|
||||
Self hosting amazing open source software is the best feeling in the world. Knowing you're not tied to someone else's servers, whims, or quirks. The ability to control how you use your own apps, and how and when you add more is what open source is all about. But what about security?
|
||||
|
||||
I self host a lot of apps, and many of them don't have any built-in authentication. While that makes it quite convenient to use them, it also makes me a bit fearful of what others may be able to do with _my_ applications and websites.
|
||||
|
||||
This is where Authelia comes in. Authelia provides a web application for authentication (make sure you are somone who should be using an application) and authorization (make sure you're permitted to use it) in front of your existing web applications.
|
||||
|
||||
As an example. I run the Homer Dashboard as a great way to link to all of my self hosted web applications. Homer itself does not (yet) have authentication. It just comes up, which is super useful and somewhat ideal, but I want to have access to my dashboard no matter where I am, so I've created a reverse proxy to it.
|
||||
|
||||
Yes, yes, there is always a VPN, or overlay network, or a dozen other ways to do it, but honestly, I just want to access my dashboard from anywhere, anytime. The reverse proxy is a great way to do that. To provide an authentication layer, though, makes me feel so much better about it. This is where something like Authelia comes into play. Now I can put Authelia in front of my Homer dash, and before the dash can be reached, a user must first authenticate.
|
||||
|
||||
!\[\](http://shownotes.opensourceisawesome.com/content/images/2021/09/authelia-on-homer.png)
|
||||
|
||||
Authelia Prompt in front of Homer Dash
|
||||
|
||||
This doesn't just have to be for web applications that don't have authentication built in. You could opt to use Authelia in front of an application with built in authentication as well. It just adds one more layer of security to your sites.
|
||||
|
||||
Today, we'll go through getting authelia setup and running.
|
||||
|
||||
What you'll need
|
||||
----------------
|
||||
|
||||
* A server that you control
|
||||
* Docker, Docker-Compose, and NGinX Proxy Manager Installed and Ready
|
||||
* A Domain / Sub-domain you want to use for your Authelia install (e.g. auth.example.com)
|
||||
* An A-record pointing to the Public IP address where your server is.
|
||||
* About 1 hour of time.
|
||||
|
||||
### Installing Docker, Docker-Compose, and NGinX Proxy Manager
|
||||
|
||||
**NOTE**: if you already have docker, docker-compose, and NGinX Proxy Manager installed, you can skip down to the section that says "Create your Authelia Entry in NGinX Proxy Manager".
|
||||
|
||||
In order to make this as painless as possible, I have built a script to install Docker and Docker-Compose for Ubuntu 18.04, 20.04, Debian, and CentOS. You can find these out on github at [https://github.com/bmcgonag/docker\_installs](https://github.com/bmcgonag/docker_installs)
|
||||
|
||||
Additionally, I have modified the Ubuntu 20.04 script into a new script that will also install NGinX Proxy Manager, and get it running in Docker for you. You can get it direclty by going to [https://gitlab.com/bmcgonag/docker\_installs/-/raw/main/install\_docker\_nproxyman.sh](https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh)
|
||||
|
||||
To use the script above, just open a terminal, SSH to your server (if you aren't already on it), and create a new file called install-docker.sh
|
||||
|
||||
`nano install-docker.sh`
|
||||
|
||||
Copy and paste the script from the github site. CTRL + C after you highlight it. Then use CTRL + Shift + V to paste it into the terminal window in your file.
|
||||
|
||||
Save it with CTRL + O, then press Enter to confirm, and then exit the nano editor with CTRL + X.
|
||||
|
||||
Now, change the permissions on the script to make it executable with:
|
||||
|
||||
`chmod +x install-docker.sh`
|
||||
|
||||
Finally, you can run the script with:
|
||||
|
||||
`./install-docker.sh`
|
||||
|
||||
This will pull down Docker-CE (Community Edition), and install it, then install Docker-Compose, and finally pull down a default docker-compose.yml file to setup and make NGinX Proxy Manager run for you.
|
||||
|
||||
NOTE: The default values in the docker-compose file are straight from the NGinX Proxy Manager Quick Start, so I highly recommend, stopping the container, and changing the DB user and password values (making sure they match in both sections of the compose file), and then restarting it.
|
||||
|
||||
Login to NGinX Proxy Manager by going to [http://your-ip-or-domain:81](http://your-ip-or-domain:81) and use the default credentials of:
|
||||
|
||||
* username: [admin@example.com](mailto:admin@example.com)
|
||||
* password: changeme
|
||||
|
||||
the first time you login, you'll be prompted to change the username email, and password to something stronger.
|
||||
|
||||
### Create your Authelia Entry in NGinX Proxy Manager
|
||||
|
||||
Now, you'll need to create an entry for the authelia front end in NGinX Proxy Manager. Somthing like `auth.your-domain.org`, of course replacing `your-domain.org` with your actual domain. Go ahead nad make sure it opens properly without SSL, then setup the LetsEncrypt SSL on your new auth domain.
|
||||
|
||||
Now, test it again, and make sure it comes up with SSL. Once that's working we'll edit it one more time, and need to add some specific text / configuration to the Advanced tab of our auth entry. For the most part this will be copy paste, with one modification.
|
||||
|
||||
```
|
||||
location / {
|
||||
set $upstream_authelia http://<authelia-server-ip-and:port>; # e.g. http://192.168.1.13:9091
|
||||
proxy_pass $upstream_authelia;
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
#Timeout if the real server is dead
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
|
||||
# Advanced Proxy Config
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 360;
|
||||
proxy_send_timeout 360;
|
||||
proxy_connect_timeout 360;
|
||||
|
||||
# Basic Proxy Config
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 64 256k;
|
||||
|
||||
# If behind reverse proxy, forwards the correct IP
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.0.0.0/8;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from fc00::/7;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
}
|
||||
```
|
||||
|
||||
In the above text, make sure to change the part where it says `<authelia-server-ip-and:port>` to be your authelia server's IP and Port number, then Save.
|
||||
|
||||
Installing Authelia
|
||||
-------------------
|
||||
|
||||
For Authelia, you'll need 3 files:
|
||||
|
||||
1. docker-compose.yml
|
||||
2. configuration.yml
|
||||
3. users\_database.yml
|
||||
|
||||
### Docker-Compose for Authelia
|
||||
|
||||
In your server, create a new folder called "authelia", and move into that folder:
|
||||
|
||||
`mkdir authelia`
|
||||
|
||||
`cd authelia`
|
||||
|
||||
Now, create two more folders called "config" and "redis"
|
||||
|
||||
`mkdir config`
|
||||
|
||||
`mkdir redis`
|
||||
|
||||
Finally, create a new file called "docker-compose.yml":
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
And paste the following text into it:
|
||||
|
||||
```
|
||||
version: '3.3'
|
||||
services:
|
||||
authelia:
|
||||
image: authelia/authelia
|
||||
volumes:
|
||||
- ./config:/config
|
||||
ports:
|
||||
- 9091:9091
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
disable: true
|
||||
environment:
|
||||
- TZ=America/Chicago
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
volumes:
|
||||
- ./redis:/data
|
||||
expose:
|
||||
- 6379
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=America/Chicago
|
||||
```
|
||||
|
||||
Once pasted, make sure to change the left side of the port mapping **if necessary** from 9091 to any free port you have on your server. If 9091 is free, then leave it as is. NOTE: if you change the port here, you must go back and change it in your NGinX Proxy Manager advanced tab, as well as the main tab for your "auth.your-dormain.org" entry.
|
||||
|
||||
Next, change the timezone ( TZ ) environment variable to your timezone.
|
||||
|
||||
Now save the file with CTRL + O, then press Enter to confirm, and use CTRL + X to exit.
|
||||
|
||||
We can't run the compose file just yet, as we have a couple of other files to create first.
|
||||
|
||||
### The Configuration File
|
||||
|
||||
Now we need to create our Authelia main configuration file. Change into the "config" directory:
|
||||
|
||||
`cd config`
|
||||
|
||||
and create a new file called "configuration.yml":
|
||||
|
||||
`nano configuration.yml`
|
||||
|
||||
In that file, paste the following: NOTE: This text has been updated since the original video and blog-post to reflect changes to the yaml for Authelia.
|
||||
|
||||
```
|
||||
###############################################################
|
||||
# Authelia configuration #
|
||||
###############################################################
|
||||
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 9091
|
||||
|
||||
jwt_secret: a-super-long-strong-string-of-letters-numbers-characters
|
||||
log:
|
||||
level: debug
|
||||
|
||||
default_redirection_url: https://auth.routemehome.org
|
||||
totp:
|
||||
issuer: routemehome.org
|
||||
period: 30
|
||||
skew: 1
|
||||
|
||||
#duo_api: ## You can use this api if you want push notifications of auth attempts
|
||||
# hostname: api-123456789.example.com
|
||||
# integration_key: ABCDEF
|
||||
# secret_key: yet-another-long-string-of-characters-and-numbers-and-symbols
|
||||
|
||||
authentication_backend:
|
||||
disable_reset_password: false
|
||||
file:
|
||||
path: /config/users_database.yml
|
||||
password:
|
||||
algorithm: argon2id
|
||||
iterations: 1
|
||||
salt_length: 16
|
||||
parallelism: 8
|
||||
memory: 64
|
||||
|
||||
access_control:
|
||||
default_policy: deny
|
||||
rules:
|
||||
# Rules applied to everyone
|
||||
- domain:
|
||||
- "noauth.domain.org"
|
||||
- "another-no-auth.domain.org"
|
||||
policy: bypass
|
||||
- domain:
|
||||
- "my1st1factor.domain.org"
|
||||
- "my2nd1factor.domain.org"
|
||||
- "domain.org"
|
||||
policy: one_factor
|
||||
# networks:
|
||||
# - 192.168.1.0/24
|
||||
- domain:
|
||||
- "a2factor.domain.org"
|
||||
policy: two_factor
|
||||
# networks:
|
||||
# - 192.168.1.0/24
|
||||
|
||||
session:
|
||||
name: authelia_session
|
||||
# This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
|
||||
secret: a-really-L0ng_s7r0ng-secr3t-st1nggggg-shoul0-be-used
|
||||
expiration: 3600 # 1 hour
|
||||
inactivity: 7200 # 2 hours
|
||||
domain: <your.domain-here.org> # Should match whatever your root protected domain is
|
||||
|
||||
redis:
|
||||
host: authelia_redis_1
|
||||
port: 6379
|
||||
# This secret can also be set using the env variables AUTHELIA_SESSION_REDIS_PASSWORD_FILE
|
||||
# password: authelia
|
||||
|
||||
regulation:
|
||||
max_retries: 5
|
||||
find_time: 2m
|
||||
ban_time: 10m
|
||||
|
||||
theme: dark
|
||||
|
||||
storage:
|
||||
encryption_key: a-very-long-strong-key-should-be-used-here
|
||||
local:
|
||||
path: /config/db.sqlite3
|
||||
|
||||
notifier:
|
||||
# filesystem:
|
||||
# filename: /config/notification.txt
|
||||
smtp:
|
||||
username: <your@email-here.com>
|
||||
password: <your-smtp-password>
|
||||
host: <your-smtp-server.url>
|
||||
port: 25,465,or 587
|
||||
sender: <sender@email-here.com>
|
||||
subject: "[Authelia] {title}"
|
||||
disable_require_tls: false
|
||||
disable_html_emails: false
|
||||
tls:
|
||||
server_name: <your-smtp-server.url>
|
||||
skip_verify: false
|
||||
minimum_version: TLS1.2
|
||||
```
|
||||
|
||||
In the above file, make sure to change any field with "<" and ">" symbols around the text. Make sure you have updated all values to meet your needs. For more information on what each of these options are, watch my video, or check the Authelia documentation.
|
||||
|
||||
Once you have pasted, and updated the file above, save it with CTRL + O, then Enter to confirm, and exit with CTRL + X.
|
||||
|
||||
### The Users Database file
|
||||
|
||||
Finally, we need to create a file for our users. This wile will be called "users\_database.yml".
|
||||
|
||||
While still in the "config" directory, create the new file:
|
||||
|
||||
`nano users_database.yml`
|
||||
|
||||
then paste the following into the file, and modify according to your needs.
|
||||
|
||||
```
|
||||
users:
|
||||
john:
|
||||
displayname: "John Doe"
|
||||
password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM"
|
||||
email: john.doe@authelia.com
|
||||
groups:
|
||||
- admins
|
||||
- dev
|
||||
harry:
|
||||
displayname: "Harry Potter"
|
||||
password: "$argon2id$v=19$m=65536,t=3,p=2$BpLnfgDsc2WD8F2q$o/vzA4myCqZZ36bUGsDY//8mKUYNZZaR0t4MFFSs+iM"
|
||||
email: harry.potter@authelia.com
|
||||
groups: []
|
||||
```
|
||||
|
||||
In the example file above, we have two users. John and Harry. If you only need 1 user, you would simply remove the section for Harry, and modify the section for John.
|
||||
|
||||
The password for the user you create must be entered as a hashed password, and not in plain text. In order to get the hashed password, you'll use the following command:
|
||||
|
||||
`docker run authelia/authelia:latest authelia hash-password 'yourpassword'`
|
||||
|
||||
Replace 'yourpassword' in the above command with the actual plain text password you want for your user.
|
||||
|
||||
Press enter, and allow the command to run. If you've not already pulled down the authelia/authelia image, it will pull down at this point from dockerhub, so be patient the first time you run this command.
|
||||
|
||||
Once complete, copy the hashed password from the command line by highlighting it, and using a right-click >> copy, or CTRL + Shift + C to copy it, and then re-open your users\_database.yml file and paste the full hash between the double quotation marks.
|
||||
|
||||
Save the file again, and you're set.
|
||||
|
||||
Test Our Authelia Setup
|
||||
-----------------------
|
||||
|
||||
We can finally test the authelia setup. We don't have any web applications protected by it just yet, but we can make sure that it's working, and that we can authenticate.
|
||||
|
||||
Move back out of the "config" directory one level with:
|
||||
|
||||
`cd ..`
|
||||
|
||||
and then run `docker-compose up`
|
||||
|
||||
This will pull down Redis, and startup Authelia and Redis. Watch the output for errors, but if everything is setup properly, you sould see a message that says Authelia is running at 0.0.0.0:9091.
|
||||
|
||||
Open your browser (or a new tab) and go to [https://auth.<your-domain.org](https://auth.<your-domain.org)\> <– of course using your actual domain.
|
||||
|
||||
You should be prompted with the login screen. You can now enter your username and password, and make sure you're able to login.
|
||||
|
||||
Setup our NGinX Proxy Manager sites for Authelia
|
||||
------------------------------------------------
|
||||
|
||||
For each site you put in the Authelia configuration file, you need to add a proxy host entry in NGinX Proxy Manager. Make sure you've setup each site in NPM, then on the Advanced tab for each one you'll need to add the following JSON. This long text only needs a few changes, and once you do it for the first site, copy and paste it from one to the next, and you'll only need to make 1 or 2 changes each time.
|
||||
|
||||
\`\`\` location /authelia { internal; set $upstream\_authelia http:///api/verify; YOUR IP AND PORT OF AUTHELIA proxy\_pass\_request\_body off; proxy\_pass $upstream\_authelia; proxy\_set\_header Content-Length "";
|
||||
|
||||
```
|
||||
# Timeout if the real server is dead
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
client_body_buffer_size 128k;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 4 32k;
|
||||
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 240;
|
||||
proxy_send_timeout 240;
|
||||
proxy_connect_timeout 240;
|
||||
```
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
location / {
|
||||
set $upstream_<appname> http://<application-ip-and:port>; #ADD IP AND PORT OF SERVICE
|
||||
proxy_pass $upstream_<appname>; #change name of the service
|
||||
|
||||
auth_request /authelia;
|
||||
auth_request_set $target_url $scheme://$http_host$request_uri;
|
||||
auth_request_set $user $upstream_http_remote_user;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
proxy_set_header Remote-User $user;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
error_page 401 =302 https://auth.<example.com>/?rd=$target_url;
|
||||
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 360;
|
||||
proxy_send_timeout 360;
|
||||
proxy_connect_timeout 360;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 64 256k;
|
||||
|
||||
# add your ip range here, and remove this comment!
|
||||
set_real_ip_from 192.168.7.0/16;
|
||||
set_real_ip_from 172.0.0.0/8;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
<figcaption>JSON for Advanced Tab of each site in NGinX Proxy Manager you want behind Authelia</figcaption></figure>In the above file, you need to change the 5 portions with the "<" and ">" around them.
|
||||
|
||||
On part 1, enter the IP and Port of your authelia server (auth.your-domain.org).
|
||||
|
||||
`<your-authelia-server-ip-and:port>` --> put your actual authelia ip and port number here. You only need to edit this the first time, then copy and paste the same config to each site you are setting up as this value will always be the same.
|
||||
|
||||
In part 2, you need to change the following:
|
||||
|
||||
`<appname>` --> whatever simple name defines the app (e.g. homer, ntop, jitsi, npmui, etc). This will be different for each entry you make in NGinX Proxy Manager for different sites.
|
||||
|
||||
<a>`application-ip-and:port`</a> --> The IP address and port number for the application you are placing behind Authelia. This will be different for each entry in NGinX Proxy Manager for different sites.
|
||||
|
||||
`auth.<example.com>` should be changed to the domain / subdomain for your authelia server. Change this the first time you make this file, then just use it over and over as this value will remain the same.
|
||||
|
||||
Finally, under the '*real ip*' section, you **may need to** add your local network IP range. For instance if your network is 10.21.0.0 based, then you'll want to add a line like:
|
||||
|
||||
`set_real_ip_from 10.21.0.0/16`
|
||||
|
||||
That's it. Save your configuration, and give it a try. NOTE: You may need to use CTRL + F5 to reresh your browser the fist time you open a page you've been to previously. Browsers tend to cache information, so making it refresh once can help.
|
||||
|
||||
Test your site, if all is setup correctly, you'll be taken to the Authelia sign in page. Depending on whether you set the site for one\_factor or two\_factor, you may also be asked to setup your TOTP app, and use your one time pin as well.
|
||||
|
||||
I hope this tutorial is helpful for you all, and look forward to using more Authelia going forward!
|
||||
|
||||
## Support My Channel and Content
|
||||
|
||||
|
||||
<figure class="kg-card kg-bookmark-card" id="bkmrk-patreon-is-a-members"><div class="kg-bookmark-content"><div class="kg-bookmark-description">Patreon is a membership platform that makes it easy for artists and creators to get paid. Join over 200,000 creators earning salaries from over 6 million monthly patrons.</div></div></figure>
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
tags:
|
||||
- Authentik
|
||||
- Docker
|
||||
---
|
||||
# 🛡️ Authentik Deployment Guide (Modern Identity Provider)
|
||||
|
||||
This guide provides the current, best-practice approach to deploying Authentik, a modern, self-hosted Identity Provider (IdP). Due to its critical position in the authentication chain, deployment must be treated as an **Enterprise Security Implementation.**
|
||||
|
||||
## I. Core Requirements & Prerequisites
|
||||
Before initiating any setup, ensure you have:
|
||||
1. A dedicated, isolated infrastructure segment for IAM services.
|
||||
2. **Centralized Secret Management:** Vault or Key Management Service (KMS) accessible to the deployment pipeline. *Never* use plain text credentials in environment files.
|
||||
|
||||
## II. Deployment Architecture (Containerized Approach)
|
||||
Authentik should be containerized (Docker Compose recommended). The architecture must enforce a strict flow:
|
||||
`Client App/Service -> Reverse Proxy (TLS 1.3) -> Authentik -> External Database/Oauth Broker`.
|
||||
|
||||
### Key Components to Configure
|
||||
* **Database:** Always use PostgreSQL or another robust, network-isolated database container for persistent store.
|
||||
* **Authentication Flow:** Design the flow around **OAuth2/OpenID Connect (OIDC)** standards. Do not rely on simple API tokens for service account access that can be hardcoded in other services.
|
||||
|
||||
## III. Modernization Practices & Security Hardening
|
||||
### 1. Strong Authentication Flows
|
||||
Modern deployments must incorporate:
|
||||
* **Multi-Factor Authentication (MFA):** Enforce TOTP/WebAuthn across all user roles, including administrators.
|
||||
* **Conditional Access:** Implement rules at the IdP level to restrict login attempts based on factors like GeoIP location or trusted network IP ranges.
|
||||
|
||||
### 2. Policy & Automation Integration
|
||||
Treat your entire identity schema as code:
|
||||
1. **Policy-as-Code (PaC):** Manage user/role group policies using dedicated manifest files and link them into the deployment artifact, rather than clicking through a GUI to set permissions.
|
||||
2. **API First:** Any integration with an internal service (e.g., Nextcloud) must be done via Authentik's exposed API endpoints; never modify the receiving service's code to expect direct database writes from another party—let the IdP handle the user lifecycle events.
|
||||
|
||||
> [!NOTE] Modernized Workflow
|
||||
In a mature enterprise setup, **Active Directory Federation Services (ADFS)** or advanced OIDC federation layers should mediate between Authentik and legacy systems (like Active Directory). The goal is to make Authentik the central source of truth for *who* has access, while external systems simply consume authenticated tokens granted by Authentik. This abstraction layer prevents security sprawl and greatly simplifies auditing.
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Monitoring
|
||||
---
|
||||
|
||||
|
||||
|
||||
CheckMK is a network and systems monitoring solution that can span from a small home user's needs into the enterprise with ease. There are many of these solutions out there, and all of them have their pros and cons, but for many of them, the con is that they are complicated to setup, maintain, and keep running.
|
||||
|
||||
Thus far, this is where CheckMK seems to be a little different. The setup is pretty straight forward, their documentation is outstanding, and the maintenance of the system seems to be quite easy.
|
||||
|
||||
If you've been looking for a monitoring solution for your various devices and networks, then this may just be the solution for you. As always, CheckMK is open source, and available in a free (community / raw) version, but the open source software is supported by the option to have more functionality / capability with their professional and enterprise level offerings as well. So, if you like CheckMK, and think it would be a good fit for your buisness, consider contributin to open source by giving them some business with their paid tiers as well.
|
||||
|
||||
What You'll Need
|
||||
----------------
|
||||
|
||||
* Either a Server (I Used and LXC Container on ProxMox) or Docker and Docker-Compose
|
||||
* If you want to use this across the cloud, then you'll also want a VPN between your various networks, or a domain name that points to the public IP of the network where you'll run CheckMK, and a reverse proxy like NGinX-Proxy-Manager.
|
||||
* About 20 minutes of your time to get started.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
In order to install CheckMK on Docker, jump down to the "Instlaling On Docker" section below. If you are installing on a regular Linux based server, then keep reading.
|
||||
|
||||
There are a pretty basic set of steps to get this installed actually. I used Ubuntu, but if you are using a different base distro, like Fedora, Cnetos, etc, then you can check [their instructions here](https://docs.checkmk.com/latest/en/install_packages.html).
|
||||
|
||||
#### Installing on Ubuntu
|
||||
|
||||
Make sure you're logged in with a non-root user that has sudo privileges. If you don't know what this means, essentially, make a new user who's not root, then give that user sudo privileges by adding them to the sudo group.
|
||||
|
||||
`adduser < your user name >`
|
||||
|
||||
Enter the password, and re-type it when prompted.
|
||||
|
||||
After completing the `adduser` portion, add the user to the "sudo" group with:
|
||||
|
||||
`usermod -aG sudo < your user name >`
|
||||
|
||||
Now logout from the root account, and login with your new user account.
|
||||
|
||||
If you need to run something with elevated privileges, just put `sudo` in front of the command. You'll be prompted for your user's password occasionally in order to run anything as "sudo".
|
||||
|
||||
To find the version for your distro and release (mine is Ubuntu 20.04 LTS), gotto [https://checkmk.com/de/download](https://checkmk.com/de/download) and select through the options down the page to filter down to your needs.
|
||||
|
||||
!\[\](http://shownotes.opensourceisawesome.com/content/images/2022/07/image.png)
|
||||
|
||||
Below that, you'll find a "wget" command, which is perfect for downloading a package to your server directly when logged in via SSH.
|
||||
|
||||
In my case the command is:
|
||||
|
||||
`wget https://download.checkmk.com/checkmk/2.1.0p8/check-mk-raw-2.1.0p8_0.focal_amd64.deb`
|
||||
|
||||
Once downloaded, we'll install it using the command:
|
||||
|
||||
`sudo apt install ./check-mk-raw-2.1.0p8_0.focal_amd64.deb`
|
||||
|
||||
Let the installer run, and you should get some output toward the end showing that the system is installed. Afterward, check that it's installed by running:
|
||||
|
||||
`omd version`
|
||||
|
||||
You should get a version number for the CheckMK you just installed.
|
||||
|
||||
Next, you need to create a "Monitoring" site. You can name the site anything, but we'll stick with what their documentation says, and call it "monitoring":
|
||||
|
||||
`omd create monitoring`
|
||||
|
||||
Note, you may need `sudo` for this step.
|
||||
|
||||
Once the monitoring site is created, you'll get a default user of `cmkadmin`, and a password that is autogenerated. Make sure to copy the password somewher so you don't lose it. You can change it via the web ui later.
|
||||
|
||||
Now, we need to start our site into a running state.
|
||||
|
||||
`omd start monitoring`
|
||||
|
||||
Again, you may need to use `sudo` in front of that command.
|
||||
|
||||
You should see output similar to this:
|
||||
|
||||
```
|
||||
Starting mkeventd...OK
|
||||
Starting liveproxyd...OK
|
||||
Starting mknotifyd...OK
|
||||
Starting rrdcached...OK
|
||||
Starting cmc...OK
|
||||
Starting apache...OK
|
||||
Starting dcd...OK
|
||||
Starting redis...OK
|
||||
Initializing Crontab...OK
|
||||
```
|
||||
|
||||
You should now be able to access your CheckMK server via your favorite modern web browser at the IP address of your host system, and the location /cmk:
|
||||
|
||||
`http://192.168.10.42/cmk` was the address I used.
|
||||
|
||||
### Installing on Docker
|
||||
|
||||
If you are like me, and you prefer to containerize anything and everything due to the simplicity of upkeep, updates, and maintenance, then you'll be more interested in running CheckMK in docker. I went through their instructions, and took a bit from here and there, and decied I wanted to create a nice docker-compose file instead of using their docker run, so that'what we'll be using. Before that, a quick section on installing Docker and Docker-Compose if you don't already have it. If you do, then skip down to the 'Installing CheckMK in Docker' secton below.
|
||||
|
||||
### Installing Docker-CE and Docker-Compose
|
||||
|
||||
If you already have Docker and Docker-Compose installed, feel free to skip down to the next section.
|
||||
|
||||
You may want to install some pre-requisite softwre as well:
|
||||
|
||||
Debian / Ubuntu
|
||||
|
||||
`sudo apt install git curl wget`
|
||||
|
||||
Fedora / Redhat
|
||||
|
||||
`dnf install git curl wget`
|
||||
|
||||
Arch
|
||||
|
||||
`sudo pacman -Sy git curl wget`
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissios to make the script executable:
|
||||
|
||||
`chmod +x ./install_docker_nproxyman.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install_docker_nproxyman.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install.
|
||||
|
||||
For instance, you may want to answer 'y' to NGinX Proxy Manager, and Portainer-CE if you don't already use these in your system.
|
||||
|
||||
At some point, you'll be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of `sudo` in front of them.
|
||||
|
||||
### Installing CheckMK on Docker
|
||||
|
||||
I like to keep all of my docker containers in a certain folder structure. Make a "docker" folder, then inside that make a new "checkmk" folder.
|
||||
|
||||
`mkdir -p docker/checkmk`
|
||||
|
||||
Next, move into the checkmk folder we just created, and make a new file called "docker-compose.yml"
|
||||
|
||||
`cd docker/checkmk`
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
Now paste the contents of the code-block below into that file:
|
||||
|
||||
```
|
||||
version: '3.3'
|
||||
services:
|
||||
check-mk-raw:
|
||||
ports:
|
||||
- '8080:5000'
|
||||
tmpfs: '/opt/omd/sites/cmk/tmp:uid=1000,gid=1000'
|
||||
volumes:
|
||||
- './monitoring:/omd/sites'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
container_name: monitoring
|
||||
restart: always
|
||||
image: 'checkmk/check-mk-raw:2.0.0-latest'
|
||||
```
|
||||
|
||||
You may want to change the left side of the port mapping in the file from 8080 to another port if 8080 is already in use on your host machine. Remember to only change the left side, leave the 5000 alone.
|
||||
|
||||
When done, save the file with CTRL + O, press Enter to confirm, and then exit the nano text editor with CTRL + X.
|
||||
|
||||
Now, we'll pull down CheckMK and start the container with the command:
|
||||
|
||||
`docker-compose up -d && docker-compose logs -f`
|
||||
|
||||
This command starts the container running first, then shows us log outpu as the container is started. We can watch for any startup errors.
|
||||
|
||||
Additionally, by watching the logs, we can see the admin username `cmkadmin` and the default password create for our admin user in the logging. We'll need this to login for the first time.
|
||||
|
||||
As long as htere are no errors you can get out of the logs view with CTRL + C.
|
||||
|
||||
Now, go to your host machine's IP and port 8080 (unless you changed it in the docker-compose file above, then use the port you set).
|
||||
|
||||
I used `http://192.168.10.112:8080`.
|
||||
|
||||
Now log in, and get ready to setup your Folders and host machines.
|
||||
|
||||
For more on how to setup a host machine (client) and the folder structure see the CheckMK docs as well as the video linked at this top of this post.
|
||||
|
||||
Support my Channel and Content
|
||||
------------------------------
|
||||
|
||||
Support my Channel and ongoing efforts through Patreon:
|
||||
[https://www.patreon.com/bePatron?u=234177](https://www.patreon.com/bePatron?u=234177)
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
---
|
||||
|
||||
This script is intended as a convenient way to configure docker's package # repositories and to install Docker Engine, This script is not recommended # for production environments. Before running this script, make yourself familiar # with potential risks and limitations, and refer to the installation manual # at https://docs.docker.com/engine/install/ for alternative installation methods.
|
||||
|
||||
\# # The script:
|
||||
|
||||
\- Requires \`root\` or \`sudo\` privileges to run.
|
||||
|
||||
\- Attempts to detect your Linux distribution and version and configure your package management system for you.
|
||||
|
||||
\- Doesn't allow you to customize most installation parameters.
|
||||
|
||||
\- Installs dependencies and recommendations without asking for confirmation.
|
||||
|
||||
\- Installs the latest stable release (by default) of Docker CLI, Docker Engine, Docker Buildx, Docker Compose, containerd, and runc. When using this script to provision a machine, this may result in unexpected major version upgrades of these packages. Always test upgrades in a test environment before # deploying to your production systems.
|
||||
|
||||
\- Isn't designed to upgrade an existing Docker installation. When using the script to update an existing installation, dependencies may not be updated to the expected version, resulting in outdated versions.
|
||||
|
||||
\# # Source code is available at https://github.com/docker/docker-install/
|
||||
|
||||
\# # Usage # ============================================================================== # #
|
||||
|
||||
To install the latest stable versions of Docker CLI, Docker Engine, and their # dependencies:
|
||||
|
||||
1\. download the script # # $ curl -fsSL https://get.docker.com -o install-docker.sh
|
||||
|
||||
2\. verify the script's content $ cat install-docker.sh
|
||||
|
||||
3\. run the script with --dry-run to verify the steps it executes $ sh install-docker.sh --dry-run
|
||||
|
||||
4\. run the script either as root, or using sudo to perform the installation. $ sudo sh install-docker.sh
|
||||
@@ -0,0 +1,224 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Security
|
||||
---
|
||||
|
||||
FreeIPA
|
||||
-------
|
||||
|
||||
### Basics
|
||||
|
||||
FreeIPA (a.k.a. Identity Management by RedHat) is a free, open source alternative to Active Directory type services for Linux / Unix.
|
||||
|
||||
The Installation of the server side works best on RedHat, Fedora, and / or CentOS systems (all RedHat based systems).
|
||||
|
||||
A client must be installed in order to join a Machine to the domain and use the IPA system for authenticaion.
|
||||
|
||||
### Requirements
|
||||
|
||||
### Server
|
||||
|
||||
* Needs to have a fixed (sttic) IP Address.
|
||||
* Needs to have a FQDN (Fully Qualified Domain Name)
|
||||
* The Domain Name must be owned by you, or a local only type domain (best to end with .local).
|
||||
* You must update the server's hostname and /etc/hosts file entries.
|
||||
* The FQDN must be first after the IP in /etc/hosts, and then the shortname afterthat.
|
||||
* Example: FQDN = ipa.mydomain.local Shortname = ipa
|
||||
|
||||
#### The Download Process
|
||||
|
||||
1. You must download the freeipa server software if it's not already in the distro you chose.
|
||||
2. You then run the installation of the software and configure the server.
|
||||
|
||||
#### DNS
|
||||
|
||||
It is extremely important to have a system setup for DNS, and to ensure that your LAN can find machines by hostname, not just by IP address.
|
||||
|
||||
* For this I use Pi-Hole. I make manual entries for the machines I'm adding to the domain.
|
||||
* I check this by using nslookup
|
||||
|
||||
If you don't have a shared server for shared home directories, you should enable the ability to make home directories for each domain user sho may log into a system.
|
||||
|
||||
You do this with the \--enablemkhomedir option on the server.
|
||||
|
||||
#### My Commands and Steps
|
||||
|
||||
Install Fedora 32 Workstation
|
||||
|
||||
Make sure it's updated completely - use sudo dnf update -y
|
||||
|
||||
Make sure you have an IP on the LAN (using Virtual Box or VirtManager you need to ensure you've setup and enabled a bridged network connection.
|
||||
|
||||
Edit the hostname and /etc/hosts files:
|
||||
|
||||
sudo nano /etc/hostname
|
||||
|
||||
make sure to enter an FQDN (can't be localhost at all).
|
||||
|
||||
Now update the /etc/hosts file using
|
||||
|
||||
sudo nano /etc/hosts
|
||||
|
||||
and make sure it looks something like
|
||||
|
||||
192.168.7.226 ipa.mydomain.local ipa
|
||||
|
||||
127.0.0.1 localhost
|
||||
|
||||
The next bits are easier to run as root, so just do
|
||||
|
||||
sudo su
|
||||
|
||||
and enter your sudo password when prompted.
|
||||
|
||||
You also need to setup your firewall to have some open ports. Luckily on Fedora this is easily accomplished with two commands.
|
||||
|
||||
firewall-cmd --add-service=freeipa-ldap --add-service=freeipa-ldaps
|
||||
|
||||
firewall-cmd --add-service=freeipa-ldap --add-service=freeipa-ldaps --permanent
|
||||
|
||||
Now, we'll pull down the freeipa seerver software.
|
||||
|
||||
yum install freeipa-server freeipa-server-dns nfs-utils
|
||||
|
||||
Next, we reboot so nfs-utils will kick in.
|
||||
|
||||
reboot
|
||||
|
||||
Once back up, go back into root:
|
||||
|
||||
sudo su
|
||||
|
||||
Enter your sudo password when prompted.
|
||||
|
||||
Once you have your pre-requisites installed and setup we'll run the ipa-server-install command and go through the steps to get our server setup.
|
||||
|
||||
ipa-server-install --mkhomedir
|
||||
|
||||
There will be some question during the process we need to answer...
|
||||
|
||||
After a successful install, you'll want to run the command
|
||||
|
||||
kinit admin
|
||||
|
||||
As this generates the necessary admin keys to get the Web UI ready for login, as well as for running admin commands from the cli if desired.
|
||||
|
||||
* * *
|
||||
|
||||
### Client Install
|
||||
|
||||
For the client install we'll use Ubuntu 20.04. Ubuntu is one of the most popular, if not the most popular desktop distributionsn for Linux, our there, thus I'm using it for this demo.
|
||||
|
||||
First, we'll install ubuntu 20.04.
|
||||
|
||||
Next, update the OS and make sure all updates are installed with
|
||||
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
Next, make sure you've setup the IP address as part of your LAN (particularly if you're using Virtualbox or VirtManager - you need to have a bridge network setup so the machine can see / reach other machines).
|
||||
|
||||
### Setup IP and FQDN
|
||||
|
||||
ip addr show
|
||||
|
||||
Will show you a list of ip addresses assigned to various network interfaces on the install.
|
||||
|
||||
You want the one that matches your LAN IP pattern.
|
||||
In my case, i'll be using the one with "192.168.7.x"
|
||||
|
||||
Next, just as with the server, we need to ensure that the IP is set as a static IP, and we need to make sure we give the machine a FQDN (Fully Qualified Domain Name - e.g. "ipa-client1.mydomain.local").
|
||||
|
||||
sudo nano /etc/hosts
|
||||
|
||||
In this file ensure you have the following setup:
|
||||
|
||||
127.0.0.1 localhost
|
||||
|
||||
127.0.1.1 ipa-client1.mydomain.local ipa-client1
|
||||
|
||||
192.168.7.x ipa-client1.mydomain.local ipa-client1
|
||||
|
||||
192.168.7.150 ipasrv2.mydomain.local ipasrv2
|
||||
|
||||
Next, make sure the "/etc/hostname" file also has the correct hosname.
|
||||
|
||||
sudo nano /etc/hostname
|
||||
|
||||
it should have something like:
|
||||
|
||||
ipa-client1.mydomain.local
|
||||
|
||||
If not, make sure to change it to the proper hostname, then save.
|
||||
|
||||
Finally, make sure to add a DNS reference in your local DNS (router, or whatever, but in my case a Pi-Hole) to the client machine FQDN and IP.
|
||||
|
||||
### Download the Software
|
||||
|
||||
Now, we need to download the freeipa client.
|
||||
|
||||
sudo apt install freeipa-client
|
||||
|
||||
While this isn't that actual client install and configuration, it will actually prompt you for a couple of bits of information, so you need to know what that is and be ready.
|
||||
|
||||
First screen in the terminal will be for "Configuring Kerberos Authentication", and will ask for the Kerberos version X realm.
|
||||
|
||||
this is basically the domain, and may be filled in by default, so if it is, just tab to 'ok', and move on. If not, type in the domain in all caps:
|
||||
|
||||
MYDOMAIN.LOCAL
|
||||
|
||||
then tab to 'Ok' and move forward.
|
||||
|
||||
Next, it will ask for the Kerberos server for your realm. This is just the FQDN of your server that we setup previously.
|
||||
|
||||
ipasrv2.mydomain.local
|
||||
|
||||
Next is the Administrative server for your Kerberos realm. It's the same server.
|
||||
|
||||
ipasrv2.mydomain.local
|
||||
|
||||
Once you've entered those items, the download / install will continue.
|
||||
|
||||
### Check your network settings one more time
|
||||
|
||||
Now, before we move forward with the final configuration and install of the freeipa client, it's a good idea to make sure that our server and client resolve to the right name and IP.
|
||||
|
||||
nslookup ipa-client1.mydomain.local
|
||||
|
||||
You should get the proper IP back.
|
||||
|
||||
nslookup ipasrv2.mydomain.local
|
||||
|
||||
Again, you should get the proper IP back.
|
||||
|
||||
### Run the final Install and Configuration
|
||||
|
||||
This is again, easier to run as root, so you can do:
|
||||
|
||||
sudo su -
|
||||
|
||||
in a terminal, and enter your sudo user password when prompted.
|
||||
|
||||
Now, we'll run our final install command for our Free IPA client machine.
|
||||
|
||||
ipa-client-install --mkhomedir
|
||||
|
||||
PLEASE NOTE: The \--mkhomedir part is VERY IMPORTANT.
|
||||
|
||||
If you do this, without that bit, and you have not setup network storage for user home directories somewhere else (and I'm not covering that here), then the client install may succeed, but upon trying to login using an LDAP user afterward, you'll get frustrated when you aren't taken to the desktop.
|
||||
|
||||
This happens becuase the system doesn't know where your home directory is, and won't create one for you without that flag.
|
||||
|
||||
#### Interactive Install Prompts
|
||||
|
||||
As with our server install, the client install has interactive prompts, and you will likely have to fill out a few bits of information as it goes through.
|
||||
|
||||
When you are done you should see a message that says:
|
||||
|
||||
`The ipa-client-install command was successful`
|
||||
|
||||
Time for one last reboot.
|
||||
|
||||
\# Logging in with LDAP / FreeIPA user
|
||||
|
||||
Before you try to login wtih LDAP, you of cource need to create a user. For this we go back to the server web ui, and get started.
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Dashboard
|
||||
---
|
||||
# **Homepage Service Documentation**
|
||||
|
||||
## **Overview**
|
||||
|
||||
**Homepage** is a self-hosted dashboard application designed for organizing and accessing web-based services. With features like bookmarks, service integrations, and Docker monitoring, it serves as a central hub for managing home labs efficiently. This guide details the configuration and setup of Homepage using Docker Compose, ensuring a simple, scalable, and maintainable deployment.
|
||||
|
||||
---
|
||||
|
||||
## **Docker Setup**
|
||||
|
||||
### **Docker Compose Configuration**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
homepage:
|
||||
image: ghcr.io/gethomepage/homepage:latest
|
||||
container_name: homepage
|
||||
environment:
|
||||
PUID: 1000 # Replace with your user ID
|
||||
PGID: 1000 # Replace with your group ID
|
||||
ports:
|
||||
- "3000:3000" # Map external port as needed
|
||||
volumes:
|
||||
- /opt/homepage/config:/app/config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro # Optional for Docker integrations
|
||||
- /opt/homepage/config/icons:/app/public/icons
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
#### **Key Configuration Details**
|
||||
|
||||
1. **Image**: Pulls the official `ghcr.io/gethomepage/homepage:latest` image for the latest features and updates.
|
||||
2. **Environment Variables**:
|
||||
- `PUID` and `PGID` ensure file permissions align with the host user, avoiding access issues.
|
||||
3. **Ports**: Maps port `3000` on the container to port `3000` on the host.
|
||||
4. **Volumes**:
|
||||
- `/opt/homepage/config`: Stores configuration files persistently.
|
||||
- `/var/run/docker.sock`: Optional for Docker container monitoring.
|
||||
- `/opt/homepage/config/icons`: Hosts custom service icons.
|
||||
5. **Restart Policy**: Ensures the service restarts automatically unless manually stopped.
|
||||
|
||||
---
|
||||
|
||||
### **Configuration Directory Structure**
|
||||
|
||||
The configuration directory `/opt/homepage/config` on the host contains all the files needed to customize and manage Homepage:
|
||||
|
||||
```plaintext
|
||||
/opt/homepage/config/
|
||||
├── bookmarks.yaml # Bookmark definitions for the dashboard
|
||||
├── config.yml # Main configuration file
|
||||
├── custom.css # Custom CSS for styling
|
||||
├── custom.js # Custom JavaScript for advanced tweaks
|
||||
├── docker.yaml # Docker container monitoring configuration
|
||||
├── icons/ # Directory for service icons
|
||||
├── kubernetes.yaml # Kubernetes integration configuration
|
||||
├── logs/ # Logs for troubleshooting
|
||||
├── services.yaml # Definitions for services displayed on the dashboard
|
||||
├── settings.yaml # General settings for Homepage
|
||||
├── settings.yaml.bck # Backup of settings
|
||||
├── widgets.yaml # Widget configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Deployment Instructions**
|
||||
|
||||
1. **Prepare Your Environment**:
|
||||
|
||||
- Install Docker and Docker Compose on your server.
|
||||
- Create the directory `/opt/homepage/config` for storing configuration files.
|
||||
2. **Deploy Homepage**:
|
||||
Save the provided `docker-compose.yml` file and start the service:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
3. **Access the Dashboard**:
|
||||
Open a web browser and navigate to:
|
||||
|
||||
```none
|
||||
http://<your-server-ip>:3000
|
||||
```
|
||||
|
||||
4. **Customize Your Dashboard**:
|
||||
|
||||
- Edit files such as `services.yaml` or `widgets.yaml` in `/opt/homepage/config`.
|
||||
- Restart the container to apply changes:
|
||||
|
||||
```bash
|
||||
docker-compose restart homepage
|
||||
```
|
||||
|
||||
5. **Add Custom Icons**:
|
||||
Place your icon files in `/opt/homepage/config/icons` and reference them in `services.yaml`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## **Additional Features**
|
||||
|
||||
### **Docker Monitoring**
|
||||
|
||||
To enable container monitoring, mount the Docker socket:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
```
|
||||
|
||||
This integration allows Homepage to display real-time container stats.
|
||||
|
||||
### **Custom Styles and Scripts**
|
||||
|
||||
- **Custom CSS**: Modify the appearance of the dashboard by editing `custom.css`.
|
||||
- **Custom JavaScript**: Add advanced functionality by editing `custom.js`.
|
||||
|
||||
---
|
||||
|
||||
## **Best Practices**
|
||||
|
||||
1. **Backup Configuration**:
|
||||
Regularly backup `/opt/homepage/config` to prevent data loss:
|
||||
|
||||
```bash
|
||||
tar -czvf homepage-config-backup.tar.gz /opt/homepage/config
|
||||
```
|
||||
|
||||
2. **Security**:
|
||||
|
||||
- Use a firewall to restrict access to port `3000` if the dashboard is for internal use only.
|
||||
- Optionally set up a reverse proxy with SSL using Nginx or Traefik.
|
||||
3. **Update Homepage**:
|
||||
Keep Homepage updated by pulling the latest image and recreating the container:
|
||||
|
||||
```bash
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## **Why Use Homepage?**
|
||||
|
||||
- **Centralized Access**: Consolidate all your services in one intuitive dashboard.
|
||||
- **Customizable**: Fully tailor the dashboard’s layout, services, and appearance to your needs.
|
||||
- **Integration Capabilities**: Monitor Docker containers, display widgets, and manage bookmarks seamlessly.
|
||||
- **Lightweight**: Minimal resource consumption ensures smooth performance in home lab environments.
|
||||
@@ -0,0 +1,257 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Security
|
||||
---
|
||||
|
||||
|
||||
I have extensive articles on installing [Authentik](https://wiki.opensourceisawesome.com/books/authentik/page/install-and-setup-authentik "Install and Setup Authentik"), Netbird, NGinX Proxy Manager, Docker, and Docker Compose. So this article is really dedicated to the configuration of Netbird to use Authentik as our IdP (Identity Provider).
|
||||
|
||||
### What You'll Need
|
||||
|
||||
* A few VPS, or VMs on which to host these services.
|
||||
* Docker and Docker Compose installed on each server (I have a script for that)
|
||||
* A domain name for which you can create sub-domains, and set A Records in DNS
|
||||
* About an hour of time.
|
||||
|
||||
### Setup your VMs or VPS
|
||||
|
||||
It will be extremely important that you setup your VPS / VMs appropriately for the workload you'll be putting on them. Also, the ability to sscale those up over time will be important as well. In the video, I use Digital Ocean for this purpose, but you are welcome to use any provider you wish, or your own hardware of course.
|
||||
|
||||
Keep in mind: Your clients will be depending on you to keep your, and their, services up and running at all times. If you use your own hardware in side your home / business, make sure you have redundancy in mind for power, connectivity, and so on.
|
||||
|
||||
### Installation of Docker and Docker Compose via a Simple Script
|
||||
|
||||
You should setup your first VM / VPS for NGinX Proxy Manager (NPM from this point on) / (if you don't already have it). Make sure that you have ports 80 and 443 accessible. Initially, you'll also need port 81, as this is where the NPM admin user interface runs. We'll create a proxy to this port, then close this port afterward (see my video for this procedure). The server should have 1 vCPU and 512 MB RAM.
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh -O install-docker.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install-docker.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install-docker.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of sudo in front of them.
|
||||
|
||||
### Install Authentik
|
||||
|
||||
For this server, I used a 1 vCPU and 2GB RAM VPS. This should give us decent performance, as well as some room to grow over time before needing to upsize.
|
||||
|
||||
For Authentik, we really just followed [my original guide](https://wiki.opensourceisawesome.com/books/authentik/page/install-and-setup-authentik "Original Guide to Install Authentik"), and didn't have to make any specific changes.
|
||||
|
||||
### Install Netbird with Authentik as the IdP
|
||||
|
||||
As always, you should really check the Netbird official documentation to ensure no major changes have occurred in their install and setup steps since this article was written. When in doubt, always go to the source.
|
||||
|
||||
Firs,t we'll be using another VPS with 1 vCPU and 2 GB RAM for this install. Additionally, we'll be using the "advanced" guide fot eh netbird install. This guide is pretty straight forward. First giving you instructions on how to get the proper / latest version of the Netbird server available.
|
||||
|
||||
NOTE: Netbird, by default, ships with the Zitadel IdP server as part of their "Quick install" solution. This is shown in my original Netbird video, so feel free to use that, and Zitadel as your IdP if you prefer.
|
||||
|
||||
We again, need to start with install Docker and Docker Compose. Once that's done, we need to get Netbird ready. This will be heavily taken from the Netbird documentation, again, make sure to check that as the source of truth.
|
||||
|
||||
First, let's run these lines to grab the Repository and Version we need to download.
|
||||
|
||||
`export REPO="https://github.com/netbirdio/netbird/"`
|
||||
|
||||
`export LATEST_TAG=$(basename $(curl -fs -o/dev/null -w %{redirect_url} ${REPO}releases/latest))`
|
||||
|
||||
To test that our commands worked, we can echo out the values of the two variables we just set:
|
||||
|
||||
`echo $REPO`
|
||||
|
||||
`echo $LATEST_TAG`
|
||||
|
||||
Those should each give you some output below the command. Next, we'll clone the repository from Github.
|
||||
|
||||
`git clone --depth 1 --branch $LATEST_TAG $REPO`
|
||||
|
||||
Now we should have a new folder called 'netbird' in the current directory. We need to move into that folder, and then into the folder inside of of called 'infrastructure\_files'.
|
||||
|
||||
`cd netbird/infrastructure_files`
|
||||
|
||||
Here, we want to copy the 'setup.env.example' file to a new file called 'setup.env'.
|
||||
|
||||
`cp setup.env.example setup.env`
|
||||
|
||||
Now we can edit the new 'setup.env' file, but still have the original example file to fall back on if needed.
|
||||
|
||||
`nano setup.env`
|
||||
|
||||
Here's my example file. You'll want to copy / paste this to your setup.env, and then change the values as stated below the file. Part of this is setting up a Provider and Application for Netbrid in Authentik.
|
||||
|
||||
```
|
||||
## example file, you can copy this file to setup.env and update its values
|
||||
##
|
||||
|
||||
# Image tags
|
||||
# you can force specific tags for each component; will be set to latest if empty
|
||||
NETBIRD_DASHBOARD_TAG=""
|
||||
NETBIRD_SIGNAL_TAG=""
|
||||
NETBIRD_MANAGEMENT_TAG=""
|
||||
COTURN_TAG=""
|
||||
|
||||
# Dashboard domain. e.g. app.mydomain.com
|
||||
NETBIRD_DOMAIN="vpn.mygreatdomain.com"
|
||||
|
||||
# TURN server domain. e.g. turn.mydomain.com
|
||||
# if not specified it will assume NETBIRD_DOMAIN
|
||||
NETBIRD_TURN_DOMAIN=""
|
||||
|
||||
# TURN server public IP address
|
||||
# required for a connection involving peers in
|
||||
# the same network as the server and external peers
|
||||
# usually matches the IP for the domain set in NETBIRD_TURN_DOMAIN
|
||||
NETBIRD_TURN_EXTERNAL_IP="210.3.42.55"
|
||||
|
||||
# -------------------------------------------
|
||||
# OIDC
|
||||
# e.g., https://example.eu.auth0.com/.well-known/openid-configuration
|
||||
# -------------------------------------------
|
||||
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://auth.mygreatdomain.com/application/o/netbird/.well-known/openid-configuration"
|
||||
NETBIRD_USE_AUTH0=false
|
||||
NETBIRD_AUTH_CLIENT_ID="copy-this-from-your-authentik-provider-information"
|
||||
NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api"
|
||||
NETBIRD_AUTH_AUDIENCE="copy-this-from-your-authentik-provider-information"
|
||||
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID="copy-this-from-your-authentik-provider-information"
|
||||
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE="copy-this-from-your-authentik-provider-information"
|
||||
|
||||
NETBIRD_MGMT_IDP="authentik"
|
||||
NETBIRD_IDP_MGMT_CLIENT_ID="copy-this-from-your-authentik-provider-information"
|
||||
NETBIRD_IDP_MGMT_EXTRA_USERNAME="Netbird"
|
||||
NETBIRD_IDP_MGMT_EXTRA_PASSWORD="this-is-a-different-key-that-your-authentik-instance-will-create-for-the-netbird-service-user"
|
||||
|
||||
# -------------------------------------------
|
||||
# Letsencrypt
|
||||
# -------------------------------------------
|
||||
# Disable letsencrypt
|
||||
# if disabled, cannot use HTTPS anymore and requires setting up a reverse-proxy to do it instead
|
||||
NETBIRD_DISABLE_LETSENCRYPT=false
|
||||
# e.g. hello@mydomain.com
|
||||
NETBIRD_LETSENCRYPT_EMAIL="myself@mygreatdomain.com"
|
||||
# -------------------------------------------
|
||||
# Extra settings
|
||||
# -------------------------------------------
|
||||
# Disable anonymous metrics collection, see more information at https://netbird.io/docs/FAQ/metrics-collection
|
||||
NETBIRD_DISABLE_ANONYMOUS_METRICS=false
|
||||
# DNS DOMAIN configures the domain name used for peer resolution. By default it is netbird.selfhosted
|
||||
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted
|
||||
```
|
||||
|
||||
In the setup.env file, make sure you fill out the NETBIRD\_DOMAIN with your intended domain / sub-domain name.
|
||||
|
||||
Additionally, you need to put in a public IPv4 address for the server where Netbird is running if you'll be relying on their coturn server which is setup automatically (I suggest this). If you want to use your own coturn server, you can, but you need to modify the resulting 'management.json' file with the appropriate details for communicating with and through your coturn server (I don't recommend this).
|
||||
|
||||
If you are using the Netbird created coturn server, you can leave the TURN\_SERVER\_DOMAIN blank (just empty double quotes ""). If, however, you are using your own coturn server, you need to fill in the domain name for that server here.
|
||||
|
||||
Next, you need to create a provider and application entry in Authentik for Netbird. Start with the provider.
|
||||
|
||||
* In Authentik go to Administrator
|
||||
* Click to expand the Applications section
|
||||
* Click 'Providers', and then select to create a new Provider in the Main UI
|
||||
* Select OpenID/OAuth Provider and click Next.
|
||||
* Fill out the form with the values
|
||||
* Name: Netbird
|
||||
* Authentication Flow: Default Authentication Flow
|
||||
* Authorization Flow: Default Authorization Flow (explicit option).
|
||||
* Under Protocol Settings select:
|
||||
* 'Public'
|
||||
* Redirect URIs: `https://<domain>`, `https://<domain>.*`, [`http://localhost:53000`](http://localhost:53000)
|
||||
* Make sure to enter each of those on a separate line, without commas.
|
||||
* Signing Key: Select the Signing Key, or feel free to use the Self-signed Key.
|
||||
* Advanced protocol settings:
|
||||
* Access code validity: `minutes=10`
|
||||
* Subject mode: `Based on the User's ID`
|
||||
|
||||
Click 'Finish'.
|
||||
|
||||
Next, we need to create an Application to go with this Provider. In the left menu, under Application, click the Applications sub-option.
|
||||
|
||||
In the main page interface, give the Application a name of 'Netbird'. Make sure to set the slug to 'netbird', then choose 'Netbird' from the Provider drop-down selection list. Additionally, under 'UI Settings', you can add the Netbird logo, as this helps make the Authentik application a little better for you and your end users (IMO).
|
||||
|
||||
Click 'Create'.
|
||||
|
||||
Now, we need to create a service user. Click on 'Directory' in the left menu, then select 'Users' underneath it.
|
||||
|
||||
In the main user interface, click the button at the top that says 'Create Service Account'.
|
||||
|
||||
Put in 'Netbird' for the username, and then disable the option for 'Create Group'.
|
||||
|
||||
Click 'Create'. Next, you'll see a window with your newly create service account user, and a password generated by Authentik. Copy this username and password information into a secure password manager. You'll need these values in your 'setup.env' file for the values of NETBIRD\_IDP\_MGMT\_EXTRA\_USERNAME and NETBIRD\_IDP\_MGMT\_EXTRA\_PASSWORD.
|
||||
|
||||
Finally, we need to add the service account we just created to the admin group in Authentik.
|
||||
|
||||
On the left menu, under 'Directory', select the 'Groups' option. In the 'Groups' view on the main user interface, select the 'authentik Admins' group by clicking on it. At the top of the window that opens, select the 'Users' tab. Click 'Add existing user', and click the '+' icon, and pick the 'Netbird' service account you just created.
|
||||
|
||||
Disable the 'Hide Service-accounts' option at the top of the view, and verify that Netbird ahs been added as an admin.
|
||||
|
||||
Whew! Done with Authentik setup now.
|
||||
|
||||
Go back to the Application >> Providers option in the left menu, and click the 'Netbird' title for the Netbird provider we created earlier. In the window that opens, select the 'OpenID Configuration URL' and copy the entire URL. Paste this value into your setup.env for the environment variable labeled 'NETBIRD\_AUTH\_OIDC\_CONFIGURATION\_ENDPOINT'.
|
||||
|
||||
Next, copy the 'Client ID' from the Authentik provider view. Paste this value in the setup.env for the following environment variables:
|
||||
|
||||
* NETBIRD\_AUTH\_CLIENT\_ID
|
||||
* NETBIRD\_AUTH\_AUDIENCE
|
||||
* NETBIRD\_AUTH\_DEVICE\_AUTH\_CLIENT\_ID
|
||||
* NETBIRD\_AUTH\_DEVICE\_AUTH\_AUDIENCE
|
||||
* NETBIRD\_IDP\_MGMT\_CLIENT\_ID
|
||||
|
||||
Finally, make sure you fill in the NETBIRD\_IDP\_MGMT\_EXTRA\_USERNAME and NETBIRD\_IDP\_MGMT\_EXTRA\_PASSWORD with the username 'Netbird' and the password that was generated by Authentik when you added the Netbird user.
|
||||
|
||||
Enter your email address for the LetsEncrypt certificate section, then save the file with CTRL + O, press Enter to confirm, and CTRL + X to exit the nano editor.
|
||||
|
||||
Build your files to run Netbird
|
||||
|
||||
Now that we have filled out our setup.env file, we need to run the script that Netbird provides for creating our docker-compose.yml and two other setup files we'll need. To do this, just run the following command in the terminal:
|
||||
|
||||
`./configure.sh`
|
||||
|
||||
The output should be a long list of environment varialbes, and where they are being set, as well as what they are being set to.
|
||||
|
||||
Now, let's move into the 'artifacts' folder. This is where those files are create by the 'configure.sh' script for us.
|
||||
|
||||
`cd artifacts`
|
||||
|
||||
Here, you can do an `ls` and see the files that are created for us. The 'management.json' and 'turnserver.conf' files are two important ones. You don't need to modify anything in these files, but if you are having trouble getting Netbird to start, and function properly, you may need to check the turn user and password in each, to ensure they match.
|
||||
|
||||
Before we try to bring up our Netbird server, let's check one more thing. We want to be sure that our hostname in the /etc/hosts file is set correctly.
|
||||
|
||||
`sudo nano /etc/hosts`
|
||||
|
||||
This will open the 'hosts' file, and you want to look for a line that may start with the ip address 127.0.1.1. If you have this line (not to be confused with the line that has 127.0.0.1), then you need to make sure that this IP is updated to be your public IP address, and that the hostname / domain are correct for your Netbird server. In my example on the video I had
|
||||
|
||||
`127.0.1.1 nb.sysmainit.com nb`
|
||||
|
||||
I had to change this value to be the public IP address of my server, so it looked more like
|
||||
|
||||
`203.66.43.152 nb.sysmainit.com nb`
|
||||
|
||||
If you need to make an edit, save your changes with CTRL + O, then press Enter to confirm, and next use CTRL + X to exit the nano editor.
|
||||
|
||||
Now we are ready to bring up our Netbird server with our Authentik IdP.
|
||||
|
||||
`docker compose up -d && docker compose logs -f`
|
||||
|
||||
The command(s) above tell docker to pull down the images and start the containers for Netbird, and to show us the log output as the containers begin to run.
|
||||
|
||||
You can look for any ERRO or ERROR messages in the logs, but they fly by pretty quickly. Give Netbird a couple fo minutes to finish it's initial startup and setup, then navigate to the domain you setup for Nebird in your browser. You should see the initial Netbird loading screen, then be redirected to your Authentik instance to log in, and after a successful authentication be re-directed back to your Netbird admin screen to start adding clients to your VPN.
|
||||
|
||||
### Support My Channel and Content
|
||||
|
||||
Support my Channel and ongoing efforts through Patreon:
|
||||
[https://www.patreon.com/awesomeopensource](https://www.patreon.com/bePatron?u=234177)
|
||||
@@ -0,0 +1,382 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Manager
|
||||
---
|
||||
https://komo.do/docs/intro
|
||||
# FerretDB
|
||||
|
||||
|
||||
- If you setup Komodo using **Postgres** or **Sqlite** options prior to [**Komodo v1.18.0**](https://github.com/moghtech/komodo/releases/tag/v1.18.0), you are using **FerretDB v1**.
|
||||
- Komodo now uses **FerretDB v2**. For existing users, [**upgrading requires a migration**](https://github.com/moghtech/komodo/blob/main/bin/util/docs/copy-database.md#ferretdb-v2-update-guide).
|
||||
|
||||
[**FerretDB**](https://www.ferretdb.com) is a MongoDB-compatible database backed by [Postgres + DocumentDB extension](https://github.com/microsoft/documentdb). It is a solid option with performance comparable to MongoDB, and can also be run on some systems which [do not support MongoDB](https://github.com/moghtech/komodo/issues/59).
|
||||
|
||||
1. Copy `komodo/ferretdb.compose.yaml` and `komodo/compose.env` to your host:
|
||||
|
||||
```
|
||||
wget -P komodo https://raw.githubusercontent.com/moghtech/komodo/main/compose/ferretdb.compose.yaml && \ wget -P komodo https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env
|
||||
```
|
||||
|
||||
2. Edit the variables in `komodo/compose.env`.
|
||||
3. Deploy:
|
||||
|
||||
```
|
||||
###################################
|
||||
|
||||
# 🦎 KOMODO COMPOSE - FERRETDB 🦎 #
|
||||
|
||||
###################################
|
||||
|
||||
|
||||
|
||||
## This compose file will deploy:
|
||||
|
||||
## 1. Postgres + FerretDB Mongo adapter (https://www.ferretdb.com)
|
||||
|
||||
## 2. Komodo Core
|
||||
|
||||
## 3. Komodo Periphery
|
||||
|
||||
|
||||
|
||||
services:
|
||||
|
||||
postgres:
|
||||
|
||||
# Recommended: Pin to a specific version
|
||||
|
||||
# https://github.com/FerretDB/documentdb/pkgs/container/postgres-documentdb
|
||||
|
||||
image: ghcr.io/ferretdb/postgres-documentdb
|
||||
|
||||
labels:
|
||||
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
# ports:
|
||||
|
||||
# - 5432:5432
|
||||
|
||||
volumes:
|
||||
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
|
||||
environment:
|
||||
|
||||
POSTGRES_USER: ${KOMODO_DB_USERNAME}
|
||||
|
||||
POSTGRES_PASSWORD: ${KOMODO_DB_PASSWORD}
|
||||
|
||||
POSTGRES_DB: postgres
|
||||
|
||||
|
||||
|
||||
ferretdb:
|
||||
|
||||
# Recommended: Pin to a specific version
|
||||
|
||||
# https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb
|
||||
|
||||
image: ghcr.io/ferretdb/ferretdb
|
||||
|
||||
labels:
|
||||
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
depends_on:
|
||||
|
||||
- postgres
|
||||
|
||||
# ports:
|
||||
|
||||
# - 27017:27017
|
||||
|
||||
volumes:
|
||||
|
||||
- ferretdb-state:/state
|
||||
|
||||
environment:
|
||||
|
||||
FERRETDB_POSTGRESQL_URL: postgres://${KOMODO_DB_USERNAME}:${KOMODO_DB_PASSWORD}@postgres:5432/postgres
|
||||
|
||||
core:
|
||||
|
||||
image: ghcr.io/moghtech/komodo-core:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
|
||||
|
||||
labels:
|
||||
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
depends_on:
|
||||
|
||||
- ferretdb
|
||||
|
||||
ports:
|
||||
|
||||
- 9120:9120
|
||||
|
||||
env_file: ./compose.env
|
||||
|
||||
environment:
|
||||
|
||||
KOMODO_DATABASE_ADDRESS: ferretdb:27017
|
||||
|
||||
KOMODO_DATABASE_USERNAME: ${KOMODO_DB_USERNAME}
|
||||
|
||||
KOMODO_DATABASE_PASSWORD: ${KOMODO_DB_PASSWORD}
|
||||
|
||||
volumes:
|
||||
|
||||
## Core cache for repos for latest commit hash / contents
|
||||
|
||||
- repo-cache:/repo-cache
|
||||
|
||||
## Store sync files on server
|
||||
|
||||
# - /path/to/syncs:/syncs
|
||||
|
||||
## Optionally mount a custom core.config.toml
|
||||
|
||||
# - /path/to/core.config.toml:/config/config.toml
|
||||
|
||||
## Allows for systemd Periphery connection at
|
||||
|
||||
## "http://host.docker.internal:8120"
|
||||
|
||||
# extra_hosts:
|
||||
|
||||
# - host.docker.internal:host-gateway
|
||||
|
||||
|
||||
|
||||
## Deploy Periphery container using this block,
|
||||
|
||||
## or deploy the Periphery binary with systemd using
|
||||
|
||||
## https://github.com/moghtech/komodo/tree/main/scripts
|
||||
|
||||
periphery:
|
||||
|
||||
image: ghcr.io/moghtech/komodo-periphery:${COMPOSE_KOMODO_IMAGE_TAG:-latest}
|
||||
|
||||
labels:
|
||||
|
||||
komodo.skip: # Prevent Komodo from stopping with StopAllContainers
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
env_file: ./compose.env
|
||||
|
||||
# Need to make sure you add this or deploying agents will be a pain.
|
||||
|
||||
ports:
|
||||
|
||||
- 8120:8120
|
||||
|
||||
volumes:
|
||||
|
||||
## Mount external docker socket
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
## Allow Periphery to see processes outside of container
|
||||
|
||||
- /proc:/proc
|
||||
|
||||
## Specify the Periphery agent root directory.
|
||||
|
||||
## Must be the same inside and outside the container,
|
||||
|
||||
## or docker will get confused. See https://github.com/moghtech/komodo/discussions/180.
|
||||
|
||||
## Default: /etc/komodo.
|
||||
|
||||
- ${PERIPHERY_ROOT_DIRECTORY:-/etc/komodo}:${PERIPHERY_ROOT_DIRECTORY:-/etc/komodo}
|
||||
|
||||
|
||||
|
||||
volumes:
|
||||
|
||||
# Postgres
|
||||
|
||||
postgres-data:
|
||||
|
||||
# FerretDB
|
||||
|
||||
ferretdb-state:
|
||||
|
||||
# Core
|
||||
|
||||
repo-cache:
|
||||
|
||||
|
||||
|
||||
# To start up - Run
|
||||
|
||||
# docker compose -p komodo -f komodo/ferretdb.compose.yaml --env-file komodo/compose.env up -d
|
||||
|
||||
|
||||
|
||||
# To stop up - Run
|
||||
|
||||
# docker compose -p komodo -f komodo/ferretdb.compose.yaml --env-file komodo/compose.env up -d
|
||||
|
||||
|
||||
|
||||
|
||||
ENV File
|
||||
####################################
|
||||
# 🦎 KOMODO COMPOSE - VARIABLES 🦎 #
|
||||
####################################
|
||||
|
||||
## These compose variables can be used with all Komodo deployment options.
|
||||
## Pass these variables to the compose up command using `--env-file komodo/compose.env`.
|
||||
## Additionally, they are passed to both Komodo Core and Komodo Periphery with `env_file: ./compose.env`,
|
||||
## so you can pass any additional environment variables to Core / Periphery directly in this file as well.
|
||||
|
||||
## Stick to a specific version, or use `latest`
|
||||
COMPOSE_KOMODO_IMAGE_TAG=latest
|
||||
|
||||
## DB credentials
|
||||
KOMODO_DB_USERNAME=admin
|
||||
KOMODO_DB_PASSWORD=PCjFCsX0yC0G44
|
||||
|
||||
## Configure a secure passkey to authenticate between Core / Periphery.
|
||||
KOMODO_PASSKEY=HModV9yPmOBD4P
|
||||
|
||||
## Set your time zone for schedules
|
||||
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
TZ=America/New_York
|
||||
|
||||
#=-------------------------=#
|
||||
#= Komodo Core Environment =#
|
||||
#=-------------------------=#
|
||||
|
||||
## Full variable list + descriptions are available here:
|
||||
## 🦎 https://github.com/moghtech/komodo/blob/main/config/core.config.toml 🦎
|
||||
|
||||
## Note. Secret variables also support `${VARIABLE}_FILE` syntax to pass docker compose secrets.
|
||||
## Docs: https://docs.docker.com/compose/how-tos/use-secrets/#examples
|
||||
|
||||
## Used for Oauth / Webhook url suggestion / Caddy reverse proxy.
|
||||
KOMODO_HOST=https://demo.komo.do
|
||||
## Displayed in the browser tab.
|
||||
KOMODO_TITLE=Komodo
|
||||
## Create a server matching this address as the "first server".
|
||||
## Use `https://host.docker.internal:8120` when using systemd-managed Periphery.
|
||||
KOMODO_FIRST_SERVER=https://192.168.2.5:8120
|
||||
## Make all buttons just double-click, rather than the full confirmation dialog.
|
||||
KOMODO_DISABLE_CONFIRM_DIALOG=true
|
||||
|
||||
## Rate Komodo polls your servers for
|
||||
## status / container status / system stats / alerting.
|
||||
## Options: 1-sec, 5-sec, 15-sec, 1-min, 5-min, 15-min
|
||||
## Default: 15-sec
|
||||
KOMODO_MONITORING_INTERVAL="15-sec"
|
||||
## Interval at which to poll Resources for any updates / automated actions.
|
||||
## Options: 15-min, 1-hr, 2-hr, 6-hr, 12-hr, 1-day
|
||||
## Default: 1-hr
|
||||
KOMODO_RESOURCE_POLL_INTERVAL="15-min"
|
||||
|
||||
## Used to auth incoming webhooks. Alt: KOMODO_WEBHOOK_SECRET_FILE
|
||||
KOMODO_WEBHOOK_SECRET=oop28TaGucFUTh
|
||||
## Used to generate jwt. Alt: KOMODO_JWT_SECRET_FILE
|
||||
KOMODO_JWT_SECRET=rm4O312hzsl6Pt
|
||||
## Time to live for jwt tokens.
|
||||
## Options: 1-hr, 12-hr, 1-day, 3-day, 1-wk, 2-wk
|
||||
KOMODO_JWT_TTL="1-day"
|
||||
|
||||
## Enable login with username + password.
|
||||
KOMODO_LOCAL_AUTH=true
|
||||
## Disable new user signups.
|
||||
KOMODO_DISABLE_USER_REGISTRATION=true
|
||||
## All new logins are auto enabled
|
||||
KOMODO_ENABLE_NEW_USERS=false
|
||||
## Disable non-admins from creating new resources.
|
||||
KOMODO_DISABLE_NON_ADMIN_CREATE=false
|
||||
## Allows all users to have Read level access to all resources.
|
||||
KOMODO_TRANSPARENT_MODE=false
|
||||
|
||||
## Prettier logging with empty lines between logs
|
||||
KOMODO_LOGGING_PRETTY=false
|
||||
## More human readable logging of startup config (multi-line)
|
||||
KOMODO_PRETTY_STARTUP_CONFIG=false
|
||||
|
||||
## OIDC Login
|
||||
KOMODO_OIDC_ENABLED=false
|
||||
## Must reachable from Komodo Core container
|
||||
# KOMODO_OIDC_PROVIDER=https://oidc.provider.internal/application/o/komodo
|
||||
## Change the host to one reachable be reachable by users (optional if it is the same as above).
|
||||
## DO NOT include the `path` part of the URL.
|
||||
# KOMODO_OIDC_REDIRECT_HOST=https://oidc.provider.external
|
||||
## Your OIDC client id
|
||||
# KOMODO_OIDC_CLIENT_ID= # Alt: KOMODO_OIDC_CLIENT_ID_FILE
|
||||
## Your OIDC client secret.
|
||||
## If your provider supports PKCE flow, this can be ommitted.
|
||||
# KOMODO_OIDC_CLIENT_SECRET= # Alt: KOMODO_OIDC_CLIENT_SECRET_FILE
|
||||
## Make usernames the full email.
|
||||
## Note. This does not work for all OIDC providers.
|
||||
# KOMODO_OIDC_USE_FULL_EMAIL=true
|
||||
## Add additional trusted audiences for token claims verification.
|
||||
## Supports comma separated list, and passing with _FILE (for compose secrets).
|
||||
# KOMODO_OIDC_ADDITIONAL_AUDIENCES=abc,123 # Alt: KOMODO_OIDC_ADDITIONAL_AUDIENCES_FILE
|
||||
|
||||
## Github Oauth
|
||||
KOMODO_GITHUB_OAUTH_ENABLED=false
|
||||
# KOMODO_GITHUB_OAUTH_ID= # Alt: KOMODO_GITHUB_OAUTH_ID_FILE
|
||||
# KOMODO_GITHUB_OAUTH_SECRET= # Alt: KOMODO_GITHUB_OAUTH_SECRET_FILE
|
||||
|
||||
## Google Oauth
|
||||
KOMODO_GOOGLE_OAUTH_ENABLED=false
|
||||
# KOMODO_GOOGLE_OAUTH_ID= # Alt: KOMODO_GOOGLE_OAUTH_ID_FILE
|
||||
# KOMODO_GOOGLE_OAUTH_SECRET= # Alt: KOMODO_GOOGLE_OAUTH_SECRET_FILE
|
||||
|
||||
## Aws - Used to launch Builder instances.
|
||||
KOMODO_AWS_ACCESS_KEY_ID= # Alt: KOMODO_AWS_ACCESS_KEY_ID_FILE
|
||||
KOMODO_AWS_SECRET_ACCESS_KEY= # Alt: KOMODO_AWS_SECRET_ACCESS_KEY_FILE
|
||||
|
||||
#=------------------------------=#
|
||||
#= Komodo Periphery Environment =#
|
||||
#=------------------------------=#
|
||||
|
||||
## Full variable list + descriptions are available here:
|
||||
## 🦎 https://github.com/moghtech/komodo/blob/main/config/periphery.config.toml 🦎
|
||||
|
||||
## Specify the root directory used by Periphery agent.
|
||||
PERIPHERY_ROOT_DIRECTORY=/etc/komodo
|
||||
|
||||
## Periphery passkeys must include KOMODO_PASSKEY to authenticate.
|
||||
PERIPHERY_PASSKEYS=${KOMODO_PASSKEY}
|
||||
|
||||
## Specify whether to disable the terminals feature
|
||||
## and disallow remote shell access (inside the Periphery container).
|
||||
PERIPHERY_DISABLE_TERMINALS=false
|
||||
|
||||
## Enable SSL using self signed certificates.
|
||||
## Connect to Periphery at https://address:8120.
|
||||
PERIPHERY_SSL_ENABLED=true
|
||||
|
||||
## If the disk size is overreporting, can use one of these to
|
||||
## whitelist / blacklist the disks to filter them, whichever is easier.
|
||||
## Accepts comma separated list of paths.
|
||||
## Usually whitelisting just /etc/hostname gives correct size.
|
||||
PERIPHERY_INCLUDE_DISK_MOUNTS=/etc/hostname
|
||||
# PERIPHERY_EXCLUDE_DISK_MOUNTS=/snap,/etc/repos
|
||||
|
||||
## Prettier logging with empty lines between logs
|
||||
PERIPHERY_LOGGING_PRETTY=false
|
||||
## More human readable logging of startup config (multi-line)
|
||||
PERIPHERY_PRETTY_STARTUP_CONFIG=false
|
||||
|
||||
```
|
||||
|
||||
|
||||
## See my compose.env & ferretdb.compose.yml files
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Email
|
||||
---
|
||||
Secure the system
|
||||
|
||||
Install UFW (sudo apt install ufw) and enable the following ports
|
||||
|
||||
|Service|Protocol|Port|Container|Variable|
|
||||
|---|---|---|---|---|
|
||||
|Postfix SMTP|TCP|25|postfix-mailcow|`${SMTP_PORT}`|
|
||||
|Postfix SMTPS|TCP|465|postfix-mailcow|`${SMTPS_PORT}`|
|
||||
|Postfix Submission|TCP|587|postfix-mailcow|`${SUBMISSION_PORT}`|
|
||||
|Dovecot IMAP|TCP|143|dovecot-mailcow|`${IMAP_PORT}`|
|
||||
|Dovecot IMAPS|TCP|993|dovecot-mailcow|`${IMAPS_PORT}`|
|
||||
|Dovecot POP3|TCP|110|dovecot-mailcow|`${POP_PORT}`|
|
||||
|Dovecot POP3S|TCP|995|dovecot-mailcow|`${POPS_PORT}`|
|
||||
|Dovecot ManageSieve|TCP|4190|dovecot-mailcow|`${SIEVE_PORT}`|
|
||||
|HTTP(S)|TCP|80/443|nginx-mailcow|`${HTTP_PORT}` / `${HTTPS_PORT}`|
|
||||
Setting up DNS Services
|
||||
## The minimal DNS configuration[¶](https://docs.mailcow.email/getstarted/prerequisite-dns/#the-minimal-dns-configuration "Permanent link")
|
||||
|
||||
This example shows you a set of records for one domain managed by mailcow. Each domain that is added to mailcow needs at least this set of records to function correctly.
|
||||
|
||||
`# Name Type Value mail IN A 1.2.3.4 autodiscover IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) autoconfig IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) @ IN MX 10 mail.example.org. (your ${MAILCOW_HOSTNAME})`
|
||||
|
||||
**Note:** The `mail` DNS record which binds the subdomain to the given ip address must only be set for the domain on which mailcow is running and that is used to access the web interface. For every other mailcow managed domain, the `MX` record will route the traffic.
|
||||
|
||||
## DKIM, SPF and DMARC[¶](https://docs.mailcow.email/getstarted/prerequisite-dns/#dkim-spf-and-dmarc "Permanent link")
|
||||
|
||||
In the example DNS zone file snippet below, a simple **SPF** TXT record is used to only allow THIS server (the MX) to send mail for your domain. Every other server is disallowed but able to ("`~all`"). Please refer to [SPF Project](http://www.open-spf.org/) for further reading.
|
||||
|
||||
`# Name Type Value @ IN TXT "v=spf1 mx a -all"`
|
||||
|
||||
It is highly recommended to create a **DKIM** TXT record in your mailcow UI and set the corresponding TXT record in your DNS records. Please refer to [OpenDKIM](http://www.opendkim.org/) for further reading.
|
||||
|
||||
`# Name Type Value dkim._domainkey IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=..."`
|
||||
|
||||
The last step in protecting yourself and others is the implementation of a **DMARC** TXT record, for example by using the [DMARC Assistant](http://www.kitterman.com/dmarc/assistant.html) ([check](https://dmarcian.com/dmarc-inspector/google.com)).
|
||||
|
||||
`# Name Type Value _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"`
|
||||
|
||||
## Testing[¶](https://docs.mailcow.email/getstarted/prerequisite-dns/#testing "Permanent link")
|
||||
|
||||
Here are some tools you can use to verify your DNS configuration:
|
||||
|
||||
- [MX Toolbox](https://mxtoolbox.com/SuperTool.aspx) (DNS, SMTP, RBL)
|
||||
- [port25.com](https://www.port25.com/dkim-wizard/) (DKIM, SPF)
|
||||
- [Mail-tester](https://www.mail-tester.com/) (DKIM, DMARC, SPF)
|
||||
- [DMARC Analyzer](https://www.dmarcanalyzer.com/spf/checker/) (DMARC, SPF)
|
||||
- [MultiRBL.valli.org](http://multirbl.valli.org/) (DNSBL, RBL, FCrDNS)
|
||||
|
||||
Insure that docker and docker-compose is install and running
|
||||
|
||||
|
||||
## Install mailcow[¶](https://docs.mailcow.email/getstarted/install/#install-mailcow "Permanent link")
|
||||
|
||||
Clone the master branch of the repository, make sure your umask equals 0022. Please clone the repository as root user and also control the stack as root. We will modify attributes - if necessary - while bootstrapping the containers automatically and make sure everything is secured. The update.sh script must therefore also be run as root. It might be necessary to change ownership and other attributes of files you will otherwise not have access to. **We drop permissions for every exposed application** and will not run an exposed service as root! Controlling the Docker daemon as non-root user does not give you additional security. The unprivileged user will spawn the containers as root likewise. The behaviour of the stack is identical.
|
||||
|
||||
`$ su # umask 0022 # <- Verify it is 0022
|
||||
cd /opt
|
||||
git clone https://github.com/mailcow/mailcow-dockerized
|
||||
cd mailcow-dockerized`
|
||||
|
||||
|
||||
## Initialize mailcow[¶](https://docs.mailcow.email/getstarted/install/#initialize-mailcow "Permanent link")
|
||||
|
||||
Generate a configuration file. Use a FQDN (`host.domain.tld`) as hostname when asked.
|
||||
|
||||
`./generate_config.sh`
|
||||
|
||||
## Start mailcow[¶](https://docs.mailcow.email/getstarted/install/#start-mailcow "Permanent link")
|
||||
|
||||
Pull the images and run the compose file. The parameter `-d` will start mailcow: dockerized detached:
|
||||
|
||||
[docker compose (Plugin)](https://docs.mailcow.email/getstarted/install/#__tabbed_1_1)[docker-compose (Standalone)](https://docs.mailcow.email/getstarted/install/#__tabbed_1_2)
|
||||
|
||||
`docker compose pull docker compose up -d`
|
||||
|
||||
|
||||
- **Administrators**:
|
||||
You can now log in as an administrator using the default credentials `admin` and the password `moohoo` at:
|
||||
**`https://${MAILCOW_HOSTNAME}/admin`**
|
||||
|
||||
- **Regular mailbox users**:
|
||||
Continue logging in at the usual URL:
|
||||
**`https://${MAILCOW_HOSTNAME}`** (FQDN only)
|
||||
|
||||
- **Domain administrators**:
|
||||
Log in at the dedicated URL:
|
||||
**`https://${MAILCOW_HOSTNAME}/domainadmin`**
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- proxy
|
||||
- Security
|
||||
---
|
||||
|
||||
|
||||
Netbird is a new offering in the Wireguard “flat” network space. They offer a great set of options and some fairly simple setup. We'll be installing this on a VPS from Digital Ocean toady.
|
||||
|
||||
Netbird reached out and asked if I'd be willing to cover their offering. I am an open source advocate, and since they are making this awesome offering open source, it only makes sense that I cover it! The best news is, they did not pay me to cover this. I do it, because this is what i do. They did however, offer up a discount code for all of you to try out their paid services. Their pricing model is already extremely affordable, so getting a 20% discount on top of that is just amazing, and I truly appreciate them offering this out to my viewers!
|
||||
|
||||
You can get a \*\*20% discount\*\* on a Team or Business plan by signing up for the plan, then emailing the \*\*discount code AWESOME\\\_OSS\*\* to \[hello\*\*@netbird.io\*\*\](mailto:hello@netbird.io) from the email address you use to sign up for the service. It's that simple!
|
||||
|
||||
Full transparency: I do have a Digital Ocean affiliate link in the description of this video. If you use it you'll get anywhere from $50 to $100 for 60 days to try out the services and offerings of Digital Ocean. If you stay with the service, I will eventually get a credit on my account as well. If you don't like the service and cancel, then I won't. Simple as that.
|
||||
|
||||
### What you'll need
|
||||
|
||||
* A server (highly recommend a cloud hosted VPS for a VPN server) - Netbird recommends 1 CPU with 2 GB RAM minimum. This is a $12 / month server on Digital Ocean.
|
||||
* Docker and Docker Compose installed.
|
||||
* Curl installed
|
||||
* jq installed
|
||||
* A domain name with an A record pointing to your public IP address (the server's public IP)
|
||||
* About 20 minutes of your time.
|
||||
|
||||
#### Quick Step List
|
||||
|
||||
1. Update your server / VPS to make sure you have the most recent packages and patches available.
|
||||
2. Install Docker and Docker-Compose
|
||||
3. Install jq and curl.
|
||||
4. Setup your domain name and A-record. NOTE: If you are using Cloudflare, you need to enable gRPC on the domain network.
|
||||
5. Check your server hosts file (/etc/hosts) and make sure that the FQDN (your domain / sub-domain) is not being pointed to by localhost 127.0.0.1 or the loopback address 127.0.1.1 (this caused me some trouble in getting the client to connect properly).
|
||||
6. Once all of this is setup, run the quick-start script on the Netbird page. [https://docs.netbird.io/selfhosted/selfhosted-quickstart](https://docs.netbird.io/selfhosted/selfhosted-quickstart)
|
||||
7. When complete, you'll be up and running. You'll have Zitadel setup for authentication, and Netbird setup with a management service that can be accessed via CLI or Web GUI.
|
||||
8. Install the Netbird client. Find the client for your OS, and install it. If using Linux, as with most tools like this, there is only a CLI option, but hopefully Netbird will get us a nice GUI option in the future.
|
||||
|
||||
* * *
|
||||
|
||||
#### Detailed Steps
|
||||
|
||||
First, let's setup our domain name and A-Record.
|
||||
|
||||
You need to own a domain, or go register a new domain. You'll need to have a public IPv4 address to the server where you plan to run Netbird. There are a whole host of ports that need to be available from the server as well, so we really need to make sure that we have all the ports forwarded if you are running behind a firewall, or from your LAN. In my case, I prefer to run a VPN from a VPS as this gives much better up-time, and isn't dependent on my home network being available.
|
||||
|
||||
I created a new droplet on Digital Ocean at the $12 / month rate which is 1 CPU and 2 GB or RAM, as detailed on the [Netbird quick start guide](https://docs.netbird.io/selfhosted/selfhosted-quickstart "Quick Start Guide from Netbird").
|
||||
|
||||
Next, make sure to setup a new domain / subdomain name. In my case I went to Cloudflare to my domain “opensourceisawesome.com”. I selected to add a new A-Record, and copied the public IPv4 address from Digital Ocean for my new VPS, and pasted it into the A-Record I created. Now I have the domain netbird.opensourceisawesome.com pointing to my public IP address on Digital Ocean.
|
||||
|
||||
NOTE: In Cloudflare, you need to enable "gRPC" for the domain you are setting this up on. You can do this by clicking on the domain, the selecting 'Network' from the left side menu. In there you'll find an option for "gRPC". Make sure this is enabled.
|
||||
|
||||
Now, I'll login to my VPS via SSH to continue my setup.
|
||||
|
||||
#### Fix Localhost / Loopback Issues
|
||||
|
||||
Quickly, look at the 'hosts' file, and make sure that you don't have your domain / subdomain name on the same line as either localhost or the loopback addresses (127.0.0.1 or 127.0.1.1).
|
||||
|
||||
In my case, I saw this
|
||||
|
||||
```
|
||||
127.0.0.1 localhost
|
||||
127.0.1.1 netbird.opensourceisawesome.com netbird
|
||||
```
|
||||
|
||||
This caused issues when trying to connect my clients. Make sure to remove the entry if your subdomain or domain are on either of these lines. Afterward you should see something like this only:
|
||||
|
||||
```
|
||||
127.0.0.1 localhost
|
||||
```
|
||||
|
||||
This will allow your domain to be reached properly if your DNS A-Record is setup correctly.
|
||||
|
||||
#### Install Docker-CE and Docker Compose
|
||||
|
||||
Next, we'll install Docker and Docker Compose. I have a script that will help you install this on the various Linux distributions out there. You can run the script by doing the following:
|
||||
|
||||
`wget -O install-docker.sh https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh?ref_type=heads`
|
||||
|
||||
This will pull down the script, and name it “install-docker.sh”.
|
||||
|
||||
Next, make the script executable with
|
||||
|
||||
`chmod +x install-docker.sh`
|
||||
|
||||
Then run the script with
|
||||
|
||||
`./install-docker.sh`
|
||||
|
||||
You'll be prompted for your sudo password if you are not running as root. After that answer ‘y’ to any items you want to install. In this instance we just need the first two options: Docker-CE and Docker Compose. You can answer ‘n’ to the rest of the options.
|
||||
|
||||
The script will install Docker-CE and Docker Compose, as well as setting the currently logged in user in the ‘docker’ group, and create a new docker network. You won't need the docker network in this case.
|
||||
|
||||
To make sure your group privileges are set on your user, you should log out and back in after the script completes.
|
||||
|
||||
Next, let's install jq and curl. I'm using Ubuntu, so I'll give those commands here, but if you use a different Linux variant, make sure to use the proper package manager for your distribution.
|
||||
|
||||
#### Install jq and curl
|
||||
|
||||
`sudo apt install jq curl -y`
|
||||
|
||||
When that completes, we'll be ready to run the one-liner command that Netbird provides to get us up and running quickly and easily.
|
||||
|
||||
#### Run the install script for Netbird:
|
||||
|
||||
`export NETBIRD_DOMAIN=netbird.example.com; curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started-with-zitadel.sh | bash`
|
||||
|
||||
where you change out the NETBIRD\_DOMAIN for your actual FQDN.
|
||||
|
||||
In my case I ran
|
||||
|
||||
`export NETBIRD_DOMAIN=netbird.opensourceisawesome.com curl -fsSL` [`https://github.com/netbirdio/netbird/releases/latest/download/getting-started-with-zitadel.sh`](https://github.com/netbirdio/netbird/releases/latest/download/getting-started-with-zitadel.sh) `bash`
|
||||
|
||||
Allow the script to complete. You'll have several docker containers running when it's done and at the bottom, you should see a message saying that the install is complete, and providing you a link to your new Netbird management site, as well as an initial username and password.
|
||||
|
||||
Copy the password, and username, and then open the site. You should be greeted by a Zitadel login page. Enter the username provided, then click 'Next'.
|
||||
|
||||
Now enter the password provided, and click 'Next'.
|
||||
|
||||
Here you'll be prompted to setup MFA (Multi-factor Authentication). Feel free to use whatever works best for you. I chose to setup a TOTP using Bitwarden. Verify the code, or method you choose, then continue. You'll be prompted to change the password, and asked for the verification code / method one more time. After that process, you'll be directed to the Netbird management page.
|
||||
|
||||
It's time to add a client.
|
||||
|
||||
### Adding a Client
|
||||
|
||||
NOTE: I did not have to run the Netbird client as sudo, which is a change from how Tailscale works.
|
||||
|
||||
Once you are at the Management console for Netbird, you can click the "Add a Peer" button. When you do you'll be presented with a pop-up message showing you a one liner to install the Netbird client on a Linux pc. You'll also be shown a multi-line method if you prefer to do it that way. At the bottom of the pop-up you'll be given a one-line command to connect your client to your Netbird server after the client application is successfully installed.
|
||||
|
||||
If you are on Windows, MacOS, Android, etc, just make sure that the tab on the pop-up is set to the OS you are using and follow the instructions as provided.
|
||||
|
||||
For Linux, we can install the client with this command:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://pkgs.netbird.io/install.sh | sh
|
||||
```
|
||||
|
||||
After the install completes, you'll see a message saying to use `netbird up` to connect If you use this command, it will attempt to connect you to the Netbird.io servers, and not your self-hosted server. To connect to your server, go back to your management page and scroll to the bottom of the 'Add Peer' pop-up window. There you'll find a more full command to bring up your Netbird client on your self hosted server. It should look something like
|
||||
|
||||
`netbird up --management-url https://netbird.youramazingdomain.com`
|
||||
|
||||
Where you'll switth out the URL [https://netbird.yojramazingdomain.com](https://netbird.yojramazingdomain.com) for your actual netbird server url.
|
||||
|
||||
When you do this, if you are doing so from a desktop machine, you'll see a browser window open up, and ask you to authenticate with your Netbird credentials. Authenticate, and you'll be told your setup is successful. You can close the browser window, and now do
|
||||
|
||||
`netbird status`
|
||||
|
||||
in your terminal, to see that Netbird is connected.
|
||||
|
||||
#### What about a server with no GUI?
|
||||
|
||||
You can also setup your Netbird VPN on a server with no GUI. Using the command line, install the Netbird client in the same way as above. Once installed, you'll need to go to your management ui in a browser, and select the "Setup Keys" tab. Here click the button for "Add Key".
|
||||
|
||||
Fill in a name for your key to identify it easily in a list.
|
||||
|
||||
Next, choose how many machines you want to setup using this key. Maybe you have 10 servers you need to add. You can do this more rapidly by using the same key for each , instead of separate keys for each.
|
||||
|
||||
If you are setting up devices in groups, select the group for the devices that will use this key, and finally set an expiration for using this key.
|
||||
|
||||
Click "Create Key".
|
||||
|
||||
Copy the Key! The won't show you this key again, so copy it as soon as you see it and store it in a password manager or encrypted file.
|
||||
|
||||
Now, on your server use the command line to add your device to the Netbird network with this command line structure:
|
||||
|
||||
`netbird up --management-url https://netbird.youramazingdomain.com --setup-key 9129F217-15CA-4DA0-2107-8ED020109879` <--- not a real key
|
||||
|
||||
You server is now connected, no separate authentication needed since you used the setup key. You can use all the Netbird CLI commands to bring your client up / down, check status, and so on.
|
||||
|
||||
Congratulations! You are now setup with a Wireguard VPN using Netbird. You have a great Web based management portal, and you have Multi-factor authentication using Zitadel for your user management.
|
||||
|
||||
#### A brief word on User Management
|
||||
|
||||
While there is a "Users" tab on your Netbird management interface, in order to add users, since it's using Zitadel for Authentication, you need to add the users through Zitadel. The good news is this is a fully functional Zitadel Authentication and IdP server. You can get to the console at
|
||||
|
||||
[https://netbird.youramazingdomain.com/ui/console](https://netbird.youramazingdomain.com/ui/console)
|
||||
|
||||
Login, using your admin credentials, and from there you can complete the Zitadel setup with branding, and user grants, as well as use Zitadel for other SSO systems you want to authenticate with.
|
||||
|
||||
This isn't a tutorial on Zitadel, but I felt like this was important for you to know. We'll cover Zitadel some other time.
|
||||
|
||||
### Support My Channel and Content
|
||||
|
||||
Support my Channel and ongoing efforts through Patreon:
|
||||
[https://www.patreon.com/awesomeopensource](https://www.patreon.com/bePatron?u=234177)
|
||||
@@ -0,0 +1,239 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Documents
|
||||
---
|
||||
|
||||
Nextcloud has come a long way over the past few years. It is truly a tool for the self-hoster, the open source enthusiast, and now it is a spectacular tool for the Open Source Businessman. You need a way to communicate with your staff, users, clients, and vendors. You want a tool that can provide you an easy way to communicate in more than one method. NExtcloud provides that all in a package that you can run in Docker.
|
||||
|
||||
Nextcloud AIO is a great way to get started with the best Nextcloud has to offer.
|
||||
|
||||
You can share files, and give permissions to clients with Nextcloud Documents. You can edit online, and see live updates with the Collabora module which gives you Libre Office features right in your browser.
|
||||
|
||||
You can Set tasks for yourself and your employees using the Tasks and Deck modules, and track progress on projects with clients, users, and even vendors through these great additional features.
|
||||
|
||||
You can setup Talk to have chat, audio, and video conversations and meeting with your various contacts. Speaking of Contacts, Nextcloud is a great way to keep up with your contacts and keep them in sync between your devices. Need a calendar to help keep your business and work life scheduled? Nextcloud has it.
|
||||
|
||||
#### What You'll Need
|
||||
|
||||
* Docker and Docker-Compose installed
|
||||
* a Reverse Proxy (I use NGinX Proxy Manager)
|
||||
* a Domain / Subdomain you own and can set an A-Record for.
|
||||
* About 45 minutes
|
||||
|
||||
Installing Docker, Docker-Compose, and NGinX Proxy Manager
|
||||
----------------------------------------------------------
|
||||
|
||||
### Installation via a Simple Script
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install_docker_nproxyman.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install_docker_nproxyman.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of `sudo` in front of them.
|
||||
|
||||
Installing Nextcloud AIO Master Container
|
||||
-----------------------------------------
|
||||
|
||||
Nextcloud AIO uses a master (main) container that you install first, and then uses access to the docker socket to then install and setup all of the Nextcloud containers for the full application.
|
||||
|
||||
First, let's create our "nextcloud" folder in our folder structure. I like to create a parent "docker" folder, then create all of my various applications in their own folders inside of that. So use the command
|
||||
|
||||
`mkdir -p docker/nextcloud`
|
||||
|
||||
That command will make the folders that don't exist, or use the folders if they do exist already.
|
||||
|
||||
Next, we'll move into the "nextcloud" folder, and create our "docker-compose.yml" file.
|
||||
|
||||
`cd docker/nextcloud`
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
Now, copy and paste the following code block into that file.
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_mastercontainer:
|
||||
name: nextcloud_aio_mastercontainer
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloud/all-in-one:latest
|
||||
restart: unless-stopped
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- 8080:8080 # change the port on the left side if it's already in use on your host system.
|
||||
environment:
|
||||
- APACHE_PORT=11000 # change this port number if 11000 is already in use on your host system.
|
||||
- APACHE_DISABLE_REWRITE_IP=1
|
||||
- NEXTCLOUD_TRUSTED_DOMAINS=< nextcloud.your-super-domain.com > < 192.168.1.129 > # Your domain name + proxy host IP
|
||||
- TRUSTED_PROXIES=< 192.168.1.129 > # proxy host IP
|
||||
```
|
||||
|
||||
In the above compose sample file, you'll need to look at a few things on your host machine to determine if you need to change them in the file. First, make sure that both ports 8080 and 11000 are not currently in use on your host machine. If either of them are in use, then change the corresponding port in the file.
|
||||
|
||||
For the port mapping of 8080:8080, only change the port number on the left side of the colon (:). DO NOT CHANGE the right side.
|
||||
|
||||
Next, you'll want to change the values surrounded by the less than "<" and greater than ">" signs on the last two lines of the compose file. Here you'll want to put in the subdomain you want for your Nextcloud AIO install.
|
||||
|
||||
YOU MUST USE A SUBDOMAIN for this install.
|
||||
|
||||
Next, you'll want to change the LAN IP of the proxy to be the proper and correct LAN IP of your reverse proxy host on both of the last two lines of the file as indicated.
|
||||
|
||||
Once you've made all of the necessary changes, save the file with CTRL + O, then press Enter to confirm, and CTRL + X to exit the nano editor.
|
||||
|
||||
Now we can run the docker-compose file with the following command:
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
The image for the nextcloud-master-container should now pull down, and start up. After you see the "done" message in the terminal, and are returned tot he prompt, wait about 30 seconds, then in your favorite browser, go to https://<your host machine IP>:8080 (or the port you changed 8080 to in the compose file).
|
||||
|
||||
I went to [`https://192.168.10.42:8080`](https://192.168.10.42:8080)
|
||||
|
||||
When the page loads, you'll be greeted by a message, and will be provided a very long password. Copy this password, and store it somewhere secure like a Bitwarden, or Vaultwarden vault. You'll need it in the next step as well, but may also need it in the future.
|
||||
|
||||
Once you've copied the password for access later, click the 'Continue' button.
|
||||
|
||||
Now, paste the password into the blank provided, and click 'Log In'.
|
||||
|
||||
You'll now see a page with a couple of blanks. The first is a blank requesting the FQDN (Fully Qualified Domain Name) of your Nextcloud AIO instance.
|
||||
|
||||
Please make sure to create an entry in your reverse proxy for the subdomain / domain you want to use for this instance, and ensure it's pointed to the host IP, and port 11000 (unless you change this port to another number, then use that port number). Additionally, make sure you setup SSL for this subdomain with certificates from a provider, or from LetsEnctrypt.
|
||||
|
||||
Once you enter your domain name into the form in the Nextcloud Master Container page, and click the Check URL button, the master conatiner will verify that the domain can be reached as typed on an SSL encrypted connection. If it can't you'll get an error, and have to fix this issue before you can proceed forward. There is an option you can set in the docker-container to disable this check, but I recommend against doing that, as the check should pass if your domain is setup correctly and can be reached.
|
||||
|
||||
### Installing Nextcloud and All of the Modules
|
||||
|
||||
Once you pass the domain check in the Nextcloud Master Container, you'll be presented with a list of modules and a checkbox next to those options. Check each option you would like installed in your Nextcloud instance, then click the 'Start Containers' button.
|
||||
|
||||
BE PATIENT! The next part will take anywhere from 5 to 25 or 30 minutes.
|
||||
|
||||
Now, we wait. In the background, the Nextcloud Master Container is pulling down all of the images for each of the Nextcloud modules that will run. It then starts those containers (much like Portainer, or Yacht do). This process takes a bit of time, but you should be able to see the status of each container in the user interface of the Master Container. It will usually refresh on it's own, but if you see it stop refreshing for a quite a while (several minutes) there should be a button to refresh / reload the data on the page. Feel free to click it. Once you see the message that all containers are in a 'Running' state, you'll get a button to Open Nextcloud, and you'll be provided a username (usually admin) and a randomly generated, long strong password for your initial login. Make sure to copy that password and use it to login to your Nextcloud install the first time.
|
||||
|
||||
### How Do I Change the Storage Location on AIO?
|
||||
|
||||
Many of you asked me, after I posted the video, how to change the storage location for the NextCloud AIO install. I have done the research and found the way. A few things to know first:
|
||||
|
||||
1. If at all possible, it's extremely important for you to set this environment variable before you ever run the AIO for the first time.
|
||||
2. If you've only started the AIO and haven't yet really invested a ton of time in syncing data, setting up users, and so on, this might be a good time for you to stop what you're doing, and really decide if you'd rather start again, but with this environment flag set.
|
||||
3. If you are already fully set in your AIO install, and have data syncing everywhere, fear not! I was in this same situation, and it is possible to still switch your main storage location, but it definitely requires a bit more work, time, and willingness to work through any issues that may come up. Overall, it was a pretty smooth process.
|
||||
4. Before you begin anything, make backups! Yes, that's plural. Make a backup using the built-in Borg Backup tool, as well as running an rsync backup of the data folder.
|
||||
5. Last, but certainly not least, check the NextCloud AIO documentation to make sure these steps are still the recommended process.
|
||||
|
||||
First, let's just discuss how to tell Nextcloud AIO to use our chosen storage location. For this, we use an environment variable in our Nextcloud AIO Mastercontainer docker-compose.yml file called NEXTCLOUD\_DATADIR. This variable does exactly what it seems like, and defines the storage location we want. In my case, I created a 1.5 TB allocation, and attached itto the VM where I run Docker. I then added the path to that location in this variable in the master-container docker compose definition file.
|
||||
|
||||
If you haven't already started running AIO, then you can define the path now, and it will be used from the very start of your Nextcloud usage, and you're essentially done. If, however, you've not done that, and you are already using your Nextcloud AIO in production, then there is more work to be done.
|
||||
|
||||
Here's what our updated docker-compose.yml file will look like with the changed option. Assume our chosen storage pasth is at /mnt/big\_storage/nextcloud
|
||||
|
||||
```
|
||||
version: "3.8"
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_mastercontainer:
|
||||
name: nextcloud_aio_mastercontainer
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloud/all-in-one:latest
|
||||
restart: unless-stopped
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- 8080:8080 # change the port on the left side if it's already in use on your host system.
|
||||
environment:
|
||||
- APACHE_PORT=11000 # change this port number if 11000 is already in use on your host system.
|
||||
- APACHE_DISABLE_REWRITE_IP=1
|
||||
- NEXTCLOUD_TRUSTED_DOMAINS=< nextcloud.your-super-domain.com > < 192.168.1.129 > # Your domain name + proxy host IP
|
||||
- TRUSTED_PROXIES=< 192.168.1.129 > # proxy host IP
|
||||
- NEXTCLOUD_DATADIR=/mnt/big_storage/nextcloud
|
||||
```
|
||||
|
||||
#### I'm already using NextCloud AIO in Production... How do _I_ change my storage location?
|
||||
|
||||
Not to worry, I was in the same boat. You **must, and I mean must** make multiple backups of your data before you start trying to change the storage location. This is just plain common sense, but I'm begging you not to rely on a single backup when making this change.
|
||||
|
||||
First, stop your nextcloud-aio-apache container, either from the command line, or using a tool like Portainer. Use whatever works best for you. From the cli, the command:
|
||||
|
||||
`docker stop nextcloud-aio-apache`
|
||||
|
||||
should get it stopped for you. Now you should be able to navigate to
|
||||
|
||||
https://<your nextcloud server ip address>:8080 (or whatever port you mapped in the docker-compose).
|
||||
|
||||
You'll be asked for your AIO Master Container password. Once you enter it, you'll see an interface where you have the option to stop the containers, make backups, change the master container password, etc.
|
||||
|
||||
1. Stop the containers. It's important to stop the containers to keep any syncing of data from happening while we make our backup.
|
||||
[](https://wiki.opensourceisawesome.com/uploads/images/gallery/2023-11/Jwkimage.png)
|
||||
|
||||
2. Once they are stopped, expand the Backup section on this page, and scroll down until you see the option to 'Create Backup'.
|
||||
[](https://wiki.opensourceisawesome.com/uploads/images/gallery/2023-11/Ow9image.png)
|
||||
|
||||
3. When the Borg Backup is complete, leave the containers stopped, and login (SSH) to your server running NextCloud AIO. You'll want to go to the path /var/lib/docker/volumes/nextcloud\_aio\_nextcloud\_data and copy or rsync all of the data in the \_data folder to back it up as well. This is our safetly backup, just in case. Best to back it up somewhere on a different machine, flash drive, external driver, NAS, etc.
|
||||
|
||||
`cd /var/lib/docker/volumes/nextcloud_aio_nextcloud_data`
|
||||
|
||||
`rsync -avzP ./_data <your_user>@<some_other_machine_ip>:/home/<your user>/nc_backup_data/`
|
||||
|
||||
4. Make sure the path you are backing up to, exists before you start.
|
||||
|
||||
5. Add the NEXTCLOUD\_DATADIR path you want for your primary storage location to the docker-compose.yml file.
|
||||
|
||||
6. Stop your NextCloud AIO Master Container, again using the CLI or a tool like Portainer.
|
||||
|
||||
`docker stop nextcloud-aio-mastercontainer`
|
||||
|
||||
7. Now. Bring up your docker-compose again so it will take the updated storage path.
|
||||
|
||||
`docker compose up -d`
|
||||
|
||||
8. Now, you'll want to go back to your NextCloud MasterContainer login at the https://<your nextcloud aio ip>:8080 (or whatever port you mapped and re-authenticate if necessary.
|
||||
|
||||
9. We need to go to the Backup section again, and now restore the last backup we made.
|
||||
[](https://wiki.opensourceisawesome.com/uploads/images/gallery/2023-11/bpVimage.png)
|
||||
|
||||
10. Choose the most recent backup date / time, and click on the 'Restore selected backup' button. Follow any confirmation rpompts and restore your data.
|
||||
|
||||
11. I used the tool "nmon" in the terminal to watch my disk reads from the primary drive, and see that my newly added 1/5 TB drive was doing writes. This gave me some confidence that the backup was being restored to the new location.
|
||||
|
||||
12. When the Master Container page shows the backup is restored, you can use the 'Start Containers' button to restart all the containers. Be patient as they restart, and keep an eye on that page. It will show you when everything is upu and running.
|
||||
|
||||
|
||||
Now it's time to test your migration and make sure you can log in.
|
||||
|
||||
NOTE: I did have to go through this process twice. My first restore did not work properly, though I have no idea why. But after deleting the restored data from my new drive, and re-running the restore, everything came up with no issues, and I had much more space for my NextCloud AIO install.
|
||||
|
||||
Once you are comfortable with the new data storage location being intact and valid, you can delete the old data from the /var/lib/docker/volumes/nextcloud\_aio\_nextcloud\_data/\_data to save space.
|
||||
|
||||
### What's Next?
|
||||
|
||||
Now that you have Nextcloud up and running, I highly recommend logging in with the given admin user, and going immediately to Users, creating a new admin level user with a long strong password, logging out of the given admin user, and logging in with your new user. Then, delete the admin user that was auto-created for you.
|
||||
|
||||
Now, go forth and be productive with all of the amazing features you're running on your new Nextcloud All-in-One installation.
|
||||
|
||||
#### Support my Channel and ongoing efforts through Patreon:
|
||||
|
||||
[https://www.patreon.com/awesomeopensource](https://www.patreon.com/awesomeopensource)
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Security
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<iframe allowfullscreen\="allowfullscreen" height\="314" src\="https://www.youtube.com/embed/PN6xDD-CGXE" width\="560"\></iframe\>
|
||||
|
||||
|
||||
|
||||
|
||||
Pi-hole is an amazing tool with tons of functionality beyond it's main purpose of filtering out ads from your devices. Now, imagine you went to all that trouble to get rid of those ads and tracking, but you still send all your requests right through your ISPs DNS servers, or Google's DNS servers, or anyone else's DNS servers.
|
||||
|
||||
|
||||
|
||||
|
||||
Instead, how about setup your own DNS server, and then tell Pi-hole to use that? It's really not difficult, so you should definitely get it setup.
|
||||
|
||||
|
||||
|
||||
|
||||
This isn't about installing or setting up Pi-hole, but here's a video that will tell you exactly how to do that.
|
||||
|
||||
|
||||
|
||||
|
||||
<iframe allowfullscreen\="allowfullscreen" height\="314" src\="https://www.youtube.com/embed/tOGlpCVoG8Q" width\="560"\></iframe\>
|
||||
|
||||
|
||||
|
||||
|
||||
This is about installing Unbound, and getting your Pi-hole to ask it for sites instead of asking your ISP or some other 3rd party for your site addresses.
|
||||
|
||||
|
||||
|
||||
|
||||
**\## Install Unbound DNS**
|
||||
|
||||
|
||||
|
||||
|
||||
We will be using Docker-CE to run Unbound, and we'll be using the mvance/unbound image as well.
|
||||
|
||||
|
||||
|
||||
|
||||
Make a directory to store our docker run command. That way we have it in the future as well.
|
||||
|
||||
|
||||
|
||||
|
||||
\`mkdir unbound-dns\`
|
||||
|
||||
|
||||
|
||||
|
||||
Next, create a file inside that folder called "docker-run.txt". It's just a text file where we'll hold our docker run command.
|
||||
|
||||
|
||||
|
||||
|
||||
\`cd unbound-dns\`
|
||||
|
||||
|
||||
|
||||
|
||||
\`nano docker-run.txt\`
|
||||
|
||||
|
||||
|
||||
|
||||
The command is very straightforward compared to a lot of docker commands we run.
|
||||
|
||||
|
||||
|
||||
|
||||
\`docker run -d --name my-unbound -p 5335:53/udp -p 5335:53/tcp --restart=always mvance/unbound:latest\`
|
||||
|
||||
|
||||
|
||||
|
||||
Simply copy that command, and paste it into the terminal file you just created above, with CTRL+Shift+V or using right-click and paste.
|
||||
|
||||
|
||||
|
||||
|
||||
Save the file with CTRL+O, then Enter, and exit using CTRL+X.
|
||||
|
||||
|
||||
|
||||
|
||||
Now, you can \`cat\` out the command with \`cat docker-run.txt\`
|
||||
|
||||
|
||||
|
||||
|
||||
Copy the command by highlighting it, then right-click and copy, or use CTRL+Shift+C.
|
||||
|
||||
|
||||
|
||||
|
||||
Now paste it back into the terminal at the prompt with CTRL+Shift+V, or right-click and paste.
|
||||
|
||||
|
||||
|
||||
|
||||
Press Enter to run it and get unbound pulled down and started.
|
||||
|
||||
|
||||
|
||||
|
||||
You can verify that unbound is running without errors when the command completes by checking that it's in docker with
|
||||
|
||||
|
||||
|
||||
|
||||
\`docker ps\`
|
||||
|
||||
|
||||
|
||||
|
||||
or you can check the logs with
|
||||
|
||||
|
||||
|
||||
|
||||
\`docker logs my-unbound\`
|
||||
|
||||
|
||||
|
||||
|
||||
If you changed the name of the container before running the command, then change it for any commands that reference the name as well.
|
||||
|
||||
|
||||
|
||||
|
||||
**\## Make Pi-hole point to Unbound**
|
||||
|
||||
|
||||
|
||||
|
||||
Now log into your Pi-hole by going to the IP address of your Pi-hole, and adding \`/admin\` to the end of the address. For instance I use
|
||||
|
||||
|
||||
|
||||
|
||||
\`http://192.168.7.242/admin\`
|
||||
|
||||
|
||||
|
||||
|
||||
Click the Login button and enter your Pi-hole password.
|
||||
|
||||
|
||||
|
||||
|
||||
Once you're logged in, you can go to Settings in the left menu, then select the DNS tab at the top of the window.
|
||||
|
||||
|
||||
|
||||
|
||||
You'll want to uncheck your currently selected upstream DNS settings on the left. On the right, under Upstream DNS Servers, click in the text field below "Custom 1 (IPv4)" and enter the IP address of the host machine your new Unbound DNS server is running on followed by "#5335". For mine it was:
|
||||
|
||||
|
||||
|
||||
|
||||
\`192.168.7.51#5335\`
|
||||
|
||||
|
||||
|
||||
|
||||
If you changed the port mapping on the docker run command, then make sure to use the port number you set after # sign instead.
|
||||
|
||||
|
||||
|
||||
|
||||
Scroll to the bottom and click 'Save'.
|
||||
|
||||
|
||||
|
||||
|
||||
Now your Pi-hole will ask your Unbound DNS server for addresses instead of the mainstream, upstream DNS providers, or your ISP.
|
||||
|
||||
|
||||
|
||||
|
||||
Sweet!
|
||||
|
||||
|
||||
|
||||
|
||||
Note that initially, requests may take a second longer as Unbound starts building its cache of data, but as you use it, it will get faster and faster.
|
||||
|
||||
|
||||
|
||||
|
||||
There you have it. Pi-hole using Unbound for DNS. Enjoy!
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Manager
|
||||
---
|
||||
# 📊 Portainer Container Orchestration Management Guide (Best Practices Edition)
|
||||
|
||||
This guide details the deployment and advanced management of Portainer, the leading User Interface for Docker and Kubernetes orchestration. Given its control over underlying resources, managing it requires treating it as a critical core service. **Always favor automated tooling (Ansible/CD system) over manual configuration.**
|
||||
|
||||
## I. Architectural Mandates & Security Posture
|
||||
Portainer’s primary function is management; therefore, securing *the management plane itself* is paramount.
|
||||
|
||||
### 🔑 Critical Hardening Checklist
|
||||
1. **Network Segmentation:** Portainer's administrative interface should be restricted via network policies (e.g., allow access only from designated admin subnets or VPN IP ranges). **Never expose port `9000` to the entire public internet.**
|
||||
2. **Authentication Layering:** Do not rely solely on built-in passwords. Integrate it with an external Identity Provider (IdP) like Authentik, OAuth2, or LDAP via a dedicated Reverse Proxy layer.
|
||||
3. **Principle of Least Privilege (PoLP):** Only grant the minimum necessary read/write scope to any user role. Administrator rights must be reserved for emergency remediation only.
|
||||
|
||||
## II. Modern Deployment Workflow (Docker Compose v3.8+)
|
||||
The following revised `docker-compose.yml` snippet is a template, emphasizing best practice container linkage:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
# 1. The Database Backend (Must be isolated and persistent)
|
||||
portainer_db:
|
||||
image: postgres:15-alpine
|
||||
container_name: portainer-db
|
||||
environment:
|
||||
POSTGRES_USER: ${DB_USER}
|
||||
POSTGRES_PASSWORD: ${DB_PASS} # Loaded from Secret Manager!
|
||||
POSTGRES_DB: portainercore
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
|
||||
# 2. Portainer Core Service
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
container_name: portainer_ui
|
||||
restart: always
|
||||
ports:
|
||||
- "9000:9000" # Exposed only AFTER Reverse Proxy handling!
|
||||
volumes:
|
||||
# The socket access is necessary but must be treated as a high privilege credential.
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- portainer_data:/data
|
||||
|
||||
volumes:
|
||||
db_data: {}
|
||||
portainer_data: {}
|
||||
```
|
||||
|
||||
## III. Management and Maintenance Automation (CI/CD Integration)
|
||||
The physical steps of `docker-compose up -d` must be replaced by an automated, version-controlled pipeline run. Any change to this file should trigger a PR review that forces the manual validation outlined in **Section IV**.
|
||||
|
||||
### 🗑️ Garbage Collection & Teardown
|
||||
Always manage resources cleanly:
|
||||
1. **Stopping:** Use `docker compose down`.
|
||||
2. **Removing Volumes (CAUTION):** If a destructive cleanup is required, use `docker volume prune` *only* after verifying that no application requires the data volume attached to it.
|
||||
3.
|
||||
### Portainer Business Edition license key
|
||||
OLD Licensing
|
||||
|
||||
3-66+D9CupP4B1Zs/6Vl9gEuM/3E/0VEI07C8DIhAGozwABg2CtkCdk8q5MLGsYXwcGBywdpHo4X9nIkcBb0MIzKjEu8+YXOC/8kqSxiOcmE+4oxkBgEIdSJr2ko43LV+C
|
||||
|
||||
3-dJTx39klJ7yVKfuMDgEyzUz4+R25qJLV7HvYZ1wpbmPxdNJvzPHrd7EFamQWHRdZKcZDjwpXO6XcLxfYyADpwSbKUZ/8RsDo/koK+PCRvQGjL9/Mq4uacakWm6kQQOI=
|
||||
|
||||
|
||||
New LIcensing
|
||||
|
||||
3-gS1eKe1FP5bwYOSWWo95U3qdjGfWRDbDvMjt1quKVcp0WC4GiBJg7jlEcodPuXIWu0aXBQa0izYvnxiEss3F09n/TRukAyS1aN6/iDRjK6N/RpPOB+XNWSD14XKIl0IYzQMwf4Ek8Q==
|
||||
- Licensed under work email
|
||||
|
||||
3-6QiSkuDnermiJXpNFu/6N1GRbExOLZnlEYP6EEg8XphhmryQi5gUmzHIbKmm4HGX+C6a/6LlN9Z9++f/DYZhQDuvHkIL6a/T7ZQvER0G00kQuQkeBNhtvU1WvzS6EjHzbmlS
|
||||
- Licensed under Miker@mcfetridge.us
|
||||
|
||||
## IV. Reference & Dependencies
|
||||
| Configuration Item | Source/Mandate | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **Docker Socket Access** | High Privilege | Requires explicit trust and granular ACL management in enterprise settings. |
|
||||
| **Persistent Storage** | `docker volume` | Always define volumes explicitly to prevent data loss during upgrades. |
|
||||
|
||||
> [!NOTE] Modernized Workflow
|
||||
Instead of manually running `docker-compose down` followed by restarts, adopt a declarative deployment framework (e.g., **FluxCD/ArgoCD**) pointed at your Git repository source of truth. This technique ensures that the *desired state* in Git is what runs everywhere, effectively treating your infrastructure documentation as code itself.
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Documents
|
||||
---
|
||||
|
||||
|
||||
Seafile is a beautifully simple, and yet really powerful syncing and drive application that you can run on your own hardware, allowing you to maintain control of your data. It gets back to the simplest concepts of data syncing, and drive usage.
|
||||
|
||||
If you've been looking to ditch Google, Dropbox, Apple, and / or Microsoft for something less intrusive, and more private, then Seafile may just be the perfect fir for you, your family, your business, and more.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
### What you'll need
|
||||
|
||||
* Docker-CE and Docker-Compose installed
|
||||
* (Optionally) Portainer or Portainer-CE Installed (Great GUI for Docker)
|
||||
* Some level of Comfort / Familiarity with the Command line (for Linux)
|
||||
* (Optionally) NGinX Proxy Manager
|
||||
|
||||
I have a video on getting [Docker-CE, Docker-Compose, Poartiner, and NGinX Proxy Manager installed with 1 script, in under 5 minutes. Check it out.](https://www.youtube.com/watch?v=TdEKVPWbC58)
|
||||
|
||||
### Parts of this Application
|
||||
|
||||
* Server - A syncing server / centralized location
|
||||
* Client - A machine or device you want to use for syncing data from and to.
|
||||
* Syncing client - The client software that syncs specified libraries (folders) between your client machine(s) and the server.
|
||||
* Drrive client - client software that creates a mounted drive where you can drop data and have it selectively synced between your client machine(s) and the server.
|
||||
|
||||
### Warning: Sync and Backup are Very Different
|
||||
|
||||
To be clear, a sync action should never be used, or confused, as a backup of data. Backups will persist data even as data changes over time.
|
||||
|
||||
A sync will synchronize the data between various machines / devices. If you delete a file from one device, the sync actioin will then delete this file from all synchronized devices. The file is not backed up.
|
||||
|
||||
### Preparation for Install
|
||||
|
||||
On your server determine a directory where your synchronized data will be stored. I highly recommend keeping your docker installs in a well organized way. Check out my video on [Docker Organization](https://www.youtube.com/watch?v=sGtTvV0xbYg&t=972s) for some ideas.
|
||||
|
||||
Now, if you are a Portainer user ( a web GUI for docker, swarm, and kubernetes control ), then you can copy and paste the code block below into a new Stack on your Portainer instance, and deploy it -- making a few changes in the file of course.
|
||||
|
||||
If you're not a Portainer user, but are interested in a terrific graphical user interface for docker, then [check out my video on installing Portainer, and Portainer Agent.](https://www.youtube.com/watch?v=-LPaWq1_GF0&t=3s)
|
||||
|
||||
If you prefer the terminal, then create a new directory called "seafile" wherever you keep all of your docker apps organized.
|
||||
|
||||
`mkdir seafile`
|
||||
|
||||
Now move into that directory
|
||||
|
||||
`cd seafile`
|
||||
|
||||
and create a new file called "docker-compose.yml":
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
Copy the code block below, and paste it into the file you just created.
|
||||
|
||||
```
|
||||
version: '2.0'
|
||||
services:
|
||||
db:
|
||||
image: mariadb:10.5
|
||||
container_name: seafile-mysql
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=<a really long strong password> # something like E48flbicuqFAgMBNX4508lke30s8d
|
||||
- MYSQL_LOG_CONSOLE=true
|
||||
volumes:
|
||||
- /path/to/your/seafile/folder/or/data/store:/var/lib/mysql
|
||||
networks:
|
||||
- seafile-net
|
||||
|
||||
memcached:
|
||||
image: memcached:1.5.6
|
||||
container_name: seafile-memcached
|
||||
entrypoint: memcached -m 256
|
||||
networks:
|
||||
- seafile-net
|
||||
|
||||
seafile:
|
||||
image: seafileltd/seafile-mc:latest
|
||||
container_name: seafile
|
||||
ports:
|
||||
- "8290:80" # you can change the left side to any open port
|
||||
volumes:
|
||||
- /path/to/your/seafile/data/storage/location/seafile-data:/shared # Requested, specifies the path to Seafile data persistent store.
|
||||
environment:
|
||||
- DB_HOST=db
|
||||
- DB_ROOT_PASSWD=< same password as above >
|
||||
- TIME_ZONE=America/Chicago # Optional, but recommended
|
||||
# - SEAFILE_ADMIN_EMAIL=me@example.com # I left this out in the video - check it out to understand why
|
||||
# - SEAFILE_ADMIN_PASSWORD=asecret # I left this out in the video - check it out to understand why
|
||||
depends_on:
|
||||
- db
|
||||
- memcached
|
||||
networks:
|
||||
- seafile-net
|
||||
|
||||
networks:
|
||||
seafile-net:
|
||||
```
|
||||
|
||||
In the yaml code you just pasted, you need to change a few items. They are indicated by being surrounded with "<" and ">" symbols. Make sure you set a long, strong db password, it's not a password you need to know or have for later, just make sure the password you create is the same in both sections of the yaml code where it's indicated.
|
||||
|
||||
Next, you need to set the absolute path to the location where you'll store your data, and the location of the database. I suggest the database be stored in your normal docker organizational location. The data itself, may be stored on a separate drive, or location due to the size you'll want to reserve for file syncing. Set both paths properly.
|
||||
|
||||
Finally, you'll want to set the port on the left side of the colon ":" to a port that is open and available on your host system. This will be the port you'll use to access your Seafile web interface.
|
||||
|
||||
Run our Seafile Container
|
||||
-------------------------
|
||||
|
||||
Now we are ready to run the docker-compose command and get your server running.
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
Once it has been pulled down, and you get the 'done' message in the terminal, use Portainer to check the logs, or you can do the command:
|
||||
|
||||
`docker-compose logs -f seafile`
|
||||
|
||||
You want to wait just a minute or two to make sure it's fully up and running.
|
||||
|
||||
Once you see an indicator that it is up, then go to your server IP and the port you set, in your browser.
|
||||
|
||||
I went to `http://192.168.10.26:8290` . You'll want to use your server IP and the port you set of course. But once, there, you'll login with the default username and password.
|
||||
|
||||
username: [me@example.com](mailto:me@example.com)
|
||||
password: asecret
|
||||
|
||||
Now, go to the System Admin section, and create a new user.
|
||||
|
||||
Once created, wait just a couple of minutes for everything to complete on the creation of your user, then make your new user an Admin. You'll want to type the first letter of the username into the field, and you'll see the option show up in the drop list. Select it, and save.
|
||||
|
||||
Now, you can delete the default user. Log out, and then log in with your new user. You'll be prompted immediately to change the password you set for the new user, so use a temporary password when first setting up the new user. Change the password now to a long, strong password, and again, you'll be prompted to login. This time you'll be logged in as your new user, and you'll have full admin rights over the system.
|
||||
|
||||
Now you can start creating libarires, other users, user groups, and so on.
|
||||
|
||||
Finally, you'll want to go to the Seafile download pages, and get the Syncing client, and the Derive client for your various machines, and mobile devices, and get them connected up to your new install.
|
||||
|
||||
You can select which libraries should be synced for each machine / device. while it's an extra step, it's also super useful to not have every thing automatically sync to every device you add.
|
||||
|
||||
Check out the video for more on setting up and configuring the Sync and Drive clients.
|
||||
|
||||
Support my Channel and Content
|
||||
------------------------------
|
||||
|
||||
Support my Channel and ongoing efforts through Patreon:
|
||||
[https://patreon.com/awesomeopensource](https://patreon.com/awesomeopensource "Support me on Patreon Link")
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Documents
|
||||
---
|
||||
|
||||
|
||||
Trilium Notes is an impressively powerful note taking application with a lot of great add-on features that allow for chart drawing, mermaid charts, Latex style numerical formulas and much more.
|
||||
|
||||
It boasts a syncing server that is fairly easy to setup, as well as desktop applications for Linux, MacOS, and Windows. The web application available via the syncing server is a literal clone of the desktop application experience, and is responsive so it works well on all of your devices.
|
||||
|
||||
[](https://wiki.opensourceisawesome.com/uploads/images/gallery/2022-11/img-0086.JPEG)
|
||||
|
||||
[](https://wiki.opensourceisawesome.com/uploads/images/gallery/2022-11/img-0087.JPEG)
|
||||
|
||||
As you can see above, the webview on the mobile device is quite usable. In fact, I'm writing up this guide using Trilium Notes. I'll copy / paste it to my Show Notes afterward…and let you know how well it converts in the Show Notes at the end.
|
||||
|
||||
### What You'll Need
|
||||
|
||||
* Sync Server
|
||||
* Docker-CE and Docker-Compose installed
|
||||
* (optional) NGinX Proxy Manager (for access from the internet)
|
||||
* Client
|
||||
* A Linux, MacOS, or Windows based PC
|
||||
* Mobile
|
||||
* A Web Browser
|
||||
* Time
|
||||
* About 15 minutes
|
||||
|
||||
#### Installation of Docker-CE and Docker-Compose (optionally NGinX Proxy Manager).
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget` [`https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh`](https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh)
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install_docker_nproxyman.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install_docker_nproxyman.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install.
|
||||
|
||||
In this case, that will be Docker-CE and Docker-Compose at a minimum, but you can also optionally install NGinX Proxy Manager if you don't already have and use another reverse proxy for your network.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of sudo in front of them.
|
||||
|
||||
### Install Trilium Notes Sync Server
|
||||
|
||||
I like to use a convention for keeping my docker containers organized. I create a parent level “docker” folder, then create an application / service folder for each application / service i want to run inside that parent folder. This allows me to run a simple backup where I just get all of the volumes and data and docker-compose files in one simple folder or zipped up file of folders under the parent “docker” folder level. If anything goes wrong I can bring the whole thing back up quickly, or even just pull out the application or service I may need.
|
||||
|
||||
For this reason I'll create a folder structure on my server like this:
|
||||
|
||||
`mkdir -p docker/trilium_notes`
|
||||
|
||||
The command above tells my system to use an existing “docker” directory if there is one, and if not, then create it, and the “trilium\_notes” directory inside of it.
|
||||
|
||||
Next, we'll move into our new application directory with the command:
|
||||
|
||||
`cd docker/trilium_notes`
|
||||
|
||||
Now we need to create our docker-compose.yml file where we'll define our Trilium Notes sync server application. I use the nano text editor in the terminal, but if you're using a desktop environment, or prefer some other text editor, feel free to use your favorite.
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
Next, copy the yaml code block below, and paste it into your fresh “docker-compose.yml” file. You can use CTRL+C to copy, and CTRL + Shift + V to paste into a terminal window.
|
||||
|
||||
```
|
||||
version: '3.3'
|
||||
services:
|
||||
trilium:
|
||||
ports:
|
||||
- '8080:8080'
|
||||
volumes:
|
||||
- '~/trilium-data:/home/node/trilium-data'
|
||||
image: 'zadam/trilium:0.56-latest'
|
||||
```
|
||||
|
||||
The above code block will do a few things.
|
||||
|
||||
1. It will create a service called “trilium”.
|
||||
2. It will forward your server's host port of 8080 to the container port of 8080. If you are already using the port 8080 on your host, you'll want to change the left side port number to some other port that is not in use on your host server. In my case I change it to 8295. So my port mapping looks like `- ‘8290:8080’`
|
||||
3. It will setup a volume in the current directory (./docker/trilium\_notes/) called “trilium-data”, and map that to the container location of “/home/node/trilium-data”. This is a good thing, as this is where our Trilium data is going to be stored, and it will be persisted between docker container updates, as well as being backed up if you setup backups of your “docker” parent folder.
|
||||
|
||||
When you've got the code block in your file, and you've made the port mapping change (if needed), you can save the file with CTRL + O, then press Enter to confirm. Take one last look and make sure everything looks ok. Remember, yaml code is space dependent, so make sure everything that is indented, is indented 2 spaces past it's parent item. Formatting should be good from my guide, but sometimes spacing can get off a bit.
|
||||
|
||||
Now press CTRL + X to exit the nano text editor.
|
||||
|
||||
Finally, we'll bring up our Trilium Notes syncing server with the command:
|
||||
|
||||
`docker-compose up -d && docker-compose logs -f`
|
||||
|
||||
This is really two commands concatenated together with the ‘&&’ signs. The first part `docker-compose up -d` starts our image pulling down, and starts our container as a daemon in the background so it continues to run even if we close the terminal window. The second part `docker-compose logs -f` tails the logs for us after the container is started. This just allows us to watch for any errors when we first start a new container.
|
||||
|
||||
Once, the image has downloaded, and the container is started, you'll see log output. When the output slows, or stops filling the xcreen with new information, you'll want to navigate in your favorite browser to the Web UI. You'll use the IP address of your host server (or localhost if you are running it on the same machine you are using), and the port you set on the left side of the por tmapping (I used port 8295).
|
||||
|
||||
I went to `https://192.168.10.42:8295` in my browser.
|
||||
|
||||
Here' you'll be presented with the first run wizard for Tilium Notes. You'll need to choose whether you want to create a new notes document, or whether you have a server you want to sync, or a desktop client you want to sync. In our case, this is new, so we can choose the first option, then click the “Next” button.
|
||||
|
||||
Now you'll be prompted to create a password for your Trilium Notes system. Choose a long, strong pasword, and use something like [Vaultwarden / Bitwarden](https://www.youtube.com/watch?v=mq7n_0Xs1Kg&t=808s) to store the password so you don't have to remember it. Even better, use one of those apps to generate a strong password for you.
|
||||
|
||||
Click Finish and you'll be logged into your new Trilium Notes server. You'll see some preset (demo) notes that will help you see what all you can do with Trilium right out of the box. I have kept those demo notes so I can reference them as I continue to use the application and grow into it's capabilities.
|
||||
|
||||
### The Trilium Desktop App
|
||||
|
||||
Next, you'll likely want a desktop app for keeping up with your notes as well. You may ask, “Why would I want a desktop app if I can just use the server for notes?” A valid question for certain.
|
||||
|
||||
The biggest reason, at least for me, is that the desktop app saves your notes locally on the desktop machine, but once you add the syncing server, the desktop app will also sync those notes to the server, and if you add notes or edit them directly on the server through a web browser, when you open the desktop app and it connects, it will sync those changes over.
|
||||
|
||||
1. This is a great duplication strategy for not losing notes.
|
||||
2. Offline functionality on the desktop in case you don't have a network connection, or are outside the network where you have syncing setup.
|
||||
|
||||
There are builds for your various Desktop Operating Systems (OSes). For Windows there are .exe options in a zipped file, and for MacOS there are packages, also in a ziipped file. For LInux, you can get a .deb, or a zipped file with a binary in it, but I highly recommend getting it from Flathub as a Flatpak for Linux.
|
||||
|
||||
No matter which way you decide to install, get the desktop installed, then run it. You'll be presented again with the first run wizard. In order to start the app syncing with the server, you'll want to select option 3, then click next. Here, you'll be prompted to enter your server address, port, and Trilium Notes password. The proxy server address, is generally not something you'll need, but if you use a proxy server in order to reach the internet (and are serving your syncing server to the internet), or you need a proxy server to get to the rest of your network, then 1. you should know that already. 2. You should enter that information in the blank provided.
|
||||
|
||||
Once you've entered all of the data needed, click “Finish Setup”, and you should get your new Desktop app interface in front of you. On the left icon panel, you should see an icon near the bottom that looks like a Wifi signal icon. This icon should show white, with no other indicators near it when everything is synced. It will show slightly differently when you need to sync a change, or if it's not connected to your server. If you see it's not connected, just open the desktop app settings by clicking the Trilium logo in the upper left corner.
|
||||
|
||||
`Trilium Icon >> Options >> Sync`
|
||||
|
||||
This path will get you to the Syncing form. Double check your entries, then use the test button to make sure the sync is working.
|
||||
|
||||
### Conclusion
|
||||
|
||||
You are set. You can now start taking notes like crazy, and you'll have some amazing syncing going on. If you are interested in syncing over the internet, then definitely check out my tutorials on setting up NGinX Proxy Manager, and using ti to expose your services to the internet, as well as getting valid SSL certificates through LetsEncrypt. It's a whole other guide, but well worth your time as you become a self hoster.
|
||||
@@ -0,0 +1,144 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Backup
|
||||
---
|
||||
|
||||
|
||||
Backups are important for so many reasons. I have had backups save my bacon more than once, and I have also learned the hard way how important backups really are. Data loss is no joke, and in this day and age there is truly no reason to have data loss.
|
||||
|
||||
Today, I want to cover a really great backup tool that is open source, and not too difficult to get setup. URBackup (like You Are Back Up! - get it?) is a really terrific tool boasting both a Server and Client installation that then makes your backup server (where you store your data) talk to your client machines (where you are backing up your data from) with some nice auto-discovery features built in.
|
||||
|
||||
Now, learn from me. Make sure your firewall has port 55414 and 55415 open so that URBackup's client and server can talk easily. You'll save yourself a lot of time and headache.
|
||||
|
||||
What you'll need
|
||||
----------------
|
||||
|
||||
* A server with enough drive space to store backups.
|
||||
* Docker and Docker Compose installed on that server - check out [https://github.com/bmcgonag/docker\_installs](https://github.com/bmcgonag/docker_installs) for some easy to use scripts for various versions of Ubuntu, Debian, and CentOS.
|
||||
* At least one client machine running either Windows, Linux, or both if you like.
|
||||
* About an hour of time.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
First, if you haven't already done so, please make sure you have both Docker-CE and Docker-Compose installed on your intended server system. This is important as it's how we will install the server portion of URBackup.
|
||||
|
||||
### Installing Docker-CE and Docker-Compose
|
||||
|
||||
### Installation via a Simple Script
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install_docker_nproxyman.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install_docker_nproxyman.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of `sudo` in front of them.
|
||||
|
||||
### Installing URBackup Server
|
||||
|
||||
Now, we'll grab the docker-compose text from the URoni/URBackup dockerhub page, and setup our space for backups.
|
||||
|
||||
1. Setup a space to store your backups.
|
||||
|
||||
`mkdir -p urbackup/{data,storage}`
|
||||
|
||||
This will setup a folder structure with a new folder called "urbackup", and two folders inside of that folder called "data" and "storage".
|
||||
|
||||
2\. Move into the "urbackup" folder:
|
||||
|
||||
`cd urbackup`
|
||||
|
||||
3\. Create a new docker-compose.yml file:
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
4\. Paste the following code into that file:
|
||||
|
||||
```
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
urbackup:
|
||||
image: uroni/urbackup-server:latest
|
||||
container_name: urbackup
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000 # Enter the UID of the user who should own the files here
|
||||
- PGID=1000 # Enter the GID of the user who should own the files here
|
||||
- TZ=America/Chicago # Enter your timezone
|
||||
volumes:
|
||||
- ./data:/var/urbackup
|
||||
- ./storage:/backups
|
||||
# Uncomment the next line if you want to bind-mount the www-folder
|
||||
#- /path/to/wwwfolder:/usr/share/urbackup
|
||||
network_mode: "host"
|
||||
# Activate the following two lines for BTRFS support
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
```
|
||||
|
||||
Save the file contents with CTRL + O, then press Enter, and exit the nano editor with CTRL + X.
|
||||
|
||||
5\. Now run the URBackup docker-compose with:
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
Once it downloads URBackup, and says "done", give it about 30 seconds, then open a web browser, and go to the ip address of your server on port 55414.
|
||||
|
||||
For instance, my server ip is 192.168.7.51, so I went to
|
||||
|
||||
`http://192.168.7.51:55414`
|
||||
|
||||
If all went well, you should now see the URBackup Server Web UI in front of you.
|
||||
|
||||
### Install a URBackup Client
|
||||
|
||||
If you are using Windows, you'll download the client application .exe file from the URBackup site ([https://urbackup.com](https://urbackup.com)). Next install the client normally, and when done, you'll use the Graphical User Interface to decide whether you want to backup only certain folders, or the entire system, etc.
|
||||
|
||||
You can go back to the URBackup Server, and refresh the page to see if the Windows machine has been autodiscovered. If not, you might waith a couple of minutes and try again. If it still doesn't show up, then make sure you don't have a firewall on that's blocking ports 55414 and 55415. These are the ports that URBackup uses to communicate between server and client.
|
||||
|
||||
#### Linux Client
|
||||
|
||||
If you are running Linux, you'll want to grab the command line command from the URBackup site, and paste it into the terminal.
|
||||
|
||||
At the time of writing the command is:
|
||||
|
||||
`TF=$(mktemp) && wget "<a href="https://hndl.urbackup.org/Client/2.4.11/UrBackup%20Client%20Linux%202.4.11.sh">https://hndl.urbackup.org/Client/2.4.11/UrBackup Client Linux 2.4.11.sh</a>" -O $TF && sudo sh $TF; rm -f $TF`
|
||||
|
||||
But, it's always best to go to the official source, and make sure the command is up to date.
|
||||
|
||||
Once pasted into the terminal, run it by pressing Enter, and enter your sudo password when prompted.
|
||||
|
||||
You may also have to enter 'Y' at some point, and choose how you want backups / snapshots to be done.
|
||||
|
||||
After everything runs, check the Web Interface, and make sure your machine shows up.
|
||||
|
||||
Now, you can enter a command to tell URBackup what to backup.
|
||||
|
||||
I chose only my Downloads folder, but give it whatever path you want.
|
||||
|
||||
`sudo urbackupclientctl add-backupdir -d /home/brian/Downloads/`
|
||||
|
||||
Run this as many times as you like to add multiple folders for backup.
|
||||
|
||||
### Support My Efforts on Patreon
|
||||
|
||||
[https://www.patreon.com/bePatron?u=234177](https://www.patreon.com/bePatron?u=234177)
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Monitoring
|
||||
---
|
||||
# **Uptime Kuma Service Documentation**
|
||||
|
||||
## **Overview**
|
||||
|
||||
**Uptime Kuma** is a modern, open-source monitoring tool that provides real-time uptime tracking for servers, websites, and services. Its user-friendly interface, detailed reporting, and customizable notifications make it an excellent alternative to hosted solutions like Uptime Robot. Hosting Uptime Kuma in your home lab offers full control and privacy, tailored to your monitoring needs.
|
||||
|
||||
---
|
||||
|
||||
## **Docker Compose Setup**
|
||||
|
||||
Deploying Uptime Kuma with Docker ensures a quick, efficient, and isolated setup. Below is the `docker-compose.yml` file configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
uptime-kuma:
|
||||
image: louislam/uptime-kuma:latest
|
||||
container_name: uptime-kuma
|
||||
restart: always
|
||||
ports:
|
||||
- "3001:3001" # Adjust the host port if necessary
|
||||
volumes:
|
||||
- /home/josh/uptime-kuma/data:/app/data # Persistent data storage
|
||||
environment:
|
||||
TZ: "America/Las_Vegas" # Set your local timezone
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Configuration Details**
|
||||
|
||||
1. **Image**:
|
||||
|
||||
- The `louislam/uptime-kuma:latest` image ensures deployment of the latest version of Uptime Kuma, complete with updates and security patches.
|
||||
2. **Container Name**:
|
||||
|
||||
- Naming the container `uptime-kuma` simplifies management and debugging.
|
||||
3. **Restart Policy**:
|
||||
|
||||
- The `restart: always` directive automatically restarts the service after failures or system reboots, ensuring reliability.
|
||||
4. **Ports**:
|
||||
|
||||
- Maps port `3001` on the host machine to the same port in the container, making the service accessible at `http://<your-server-ip>:3001`.
|
||||
5. **Volumes**:
|
||||
|
||||
- Data is persistently stored in `/home/josh/uptime-kuma/data` on the host, ensuring monitoring history and configurations are preserved.
|
||||
6. **Environment Variables**:
|
||||
|
||||
- Configures the service to use the `"America/Las_Vegas"` timezone, aligning notifications and logs with local time.
|
||||
|
||||
---
|
||||
|
||||
## **Deployment Steps**
|
||||
|
||||
1. **Prepare the Host Environment**:
|
||||
|
||||
- Create the directory for persistent storage:
|
||||
|
||||
```bash
|
||||
mkdir -p /home/josh/uptime-kuma/data
|
||||
```
|
||||
|
||||
2. **Deploy Uptime Kuma**:
|
||||
|
||||
- Run the following command to start the service:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
3. **Access the Uptime Kuma Dashboard**:
|
||||
|
||||
- Open a web browser and navigate to:
|
||||
|
||||
```none
|
||||
http://<your-server-ip>:3001
|
||||
```
|
||||
|
||||
4. **Configure Monitors**:
|
||||
|
||||
- Log in to the dashboard and add monitors for servers, websites, or other services you wish to track.
|
||||
|
||||
---
|
||||
|
||||
## **Benefits of This Setup**
|
||||
|
||||
1. **Ease of Deployment**:
|
||||
|
||||
- Docker Compose simplifies the process, making setup quick and maintenance straightforward.
|
||||
2. **Persistent Data**:
|
||||
|
||||
- All configurations, logs, and monitoring data are preserved across updates or container restarts.
|
||||
3. **Scalability**:
|
||||
|
||||
- Easily add more monitors or expand the system as your needs grow.
|
||||
4. **Custom Notifications**:
|
||||
|
||||
- Configure notifications via email, Telegram, Slack, or other integrations to stay informed.
|
||||
|
||||
---
|
||||
|
||||
## **Troubleshooting**
|
||||
|
||||
- **Service Not Accessible**:
|
||||
|
||||
- Ensure the container is running:
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
- Check logs for errors:
|
||||
|
||||
```bash
|
||||
docker logs uptime-kuma
|
||||
```
|
||||
|
||||
- **Port Conflicts**:
|
||||
|
||||
- If port `3001` is already in use, modify the `ports` configuration:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "custom-port:3001"
|
||||
```
|
||||
|
||||
- Restart the service:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## **Additional Resources**
|
||||
|
||||
- [Uptime Kuma GitHub Repository](https://github.com/louislam/uptime-kuma)
|
||||
- [Docker Documentation](https://docs.docker.com/)
|
||||
- [Uptime Kuma Wiki](https://github.com/louislam/uptime-kuma/wiki)
|
||||
|
||||
---
|
||||
|
||||
## **Conclusion**
|
||||
|
||||
This Docker Compose setup provides a robust and reliable foundation for monitoring your home lab's uptime and status. With its real-time insights, customizable alerts, and modern design, Uptime Kuma ensures your systems remain operational and your services run smoothly. 🚀
|
||||
@@ -0,0 +1,173 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Manager
|
||||
---
|
||||
# **Vaultwarden Setup and Configuration**
|
||||
|
||||
## **Overview**
|
||||
|
||||
Vaultwarden (formerly Bitwarden_RS) is a lightweight, open-source password management server designed to be an alternative to the official Bitwarden server. It offers an efficient, self-hosted solution to securely manage passwords, notes, and sensitive data. Vaultwarden is ideal for home labs due to its minimal resource requirements and robust feature set.
|
||||
|
||||
---
|
||||
|
||||
## **Docker Compose Configuration**
|
||||
|
||||
Deploying Vaultwarden with Docker Compose ensures ease of setup, portability, and maintainability. Below is the configuration file:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
vaultwarden:
|
||||
image: vaultwarden/server:latest
|
||||
container_name: vaultwarden
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DOMAIN: "https://vaultwarden.lan" # Replace with your domain or IP
|
||||
ADMIN_TOKEN: "<secure-random-token>" # Replace with a secure admin token
|
||||
LOG_LEVEL: "info" # Adjust log verbosity (debug, info, warn, error)
|
||||
ports:
|
||||
- "80:80" # HTTP port
|
||||
- "443:443" # HTTPS port
|
||||
volumes:
|
||||
- vaultwarden-data:/data
|
||||
networks:
|
||||
- vaultwarden-net
|
||||
|
||||
volumes:
|
||||
vaultwarden-data:
|
||||
|
||||
networks:
|
||||
vaultwarden-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Configuration Details**
|
||||
|
||||
### **1. Image and Container**
|
||||
|
||||
- **Image**: The `vaultwarden/server:latest` image provides the latest stable release.
|
||||
- **Container Name**: The container is named `vaultwarden` for clarity and easy identification in Docker commands.
|
||||
|
||||
### **2. Environment Variables**
|
||||
|
||||
- **DOMAIN**: Specifies the Vaultwarden service's domain or IP address. Replace `https://vaultwarden.lan` with your domain or IP.
|
||||
- **ADMIN_TOKEN**: A secure token for accessing the admin panel. Generate one using:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 48
|
||||
```
|
||||
|
||||
- **LOG_LEVEL**: Controls log verbosity. Default is `info`, but you can use `debug`, `warn`, or `error` based on your monitoring needs.
|
||||
|
||||
### **3. Ports**
|
||||
|
||||
- Maps HTTP (80) and HTTPS (443) ports to the host. HTTPS ensures secure communication, especially when accessed remotely.
|
||||
|
||||
### **4. Volumes**
|
||||
|
||||
- **`vaultwarden-data`**: Persists all Vaultwarden data, including user credentials and server configurations, across container restarts and updates.
|
||||
|
||||
### **5. Network**
|
||||
|
||||
- **Bridge Network**: Vaultwarden runs on a dedicated Docker bridge network, isolating it from other containers for added security.
|
||||
|
||||
---
|
||||
|
||||
## **Deployment Steps**
|
||||
|
||||
1. **Prepare Your Environment**
|
||||
|
||||
- Ensure Docker and Docker Compose are installed on your host.
|
||||
2. **Create the `docker-compose.yml` File**
|
||||
|
||||
- Save the above configuration as `docker-compose.yml` in your preferred directory.
|
||||
3. **Generate an Admin Token**
|
||||
|
||||
- Run the following command to generate a secure admin token:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 48
|
||||
```
|
||||
|
||||
- Replace `<secure-random-token>` in the `ADMIN_TOKEN` field with the generated token.
|
||||
4. **Start the Service**
|
||||
|
||||
- Deploy Vaultwarden with:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
5. **Access Vaultwarden**
|
||||
|
||||
- Open a web browser and navigate to `http://<server-ip>` (or `https://<your-domain>` if HTTPS is configured).
|
||||
6. **Admin Panel**
|
||||
|
||||
- Access the admin panel at `http://<server-ip>/admin` (or `https://<your-domain>/admin`) using the `ADMIN_TOKEN`.
|
||||
|
||||
---
|
||||
|
||||
## **Enhancing Security**
|
||||
|
||||
- **Enable HTTPS**:
|
||||
|
||||
- Use a reverse proxy like NGINX or Traefik to configure SSL with Let's Encrypt.
|
||||
- Alternatively, generate a self-signed certificate or import an existing SSL certificate.
|
||||
- **Firewall Configuration**:
|
||||
|
||||
- Restrict access to the admin panel (`/admin`) to trusted IPs using a firewall or reverse proxy.
|
||||
- **Regular Backups**:
|
||||
|
||||
- Backup the `vaultwarden-data` volume to prevent data loss:
|
||||
|
||||
```bash
|
||||
docker run --rm -v vaultwarden-data:/data -v $(pwd):/backup alpine tar czf /backup/vaultwarden-backup.tar.gz /data
|
||||
```
|
||||
|
||||
- **Use a Strong Admin Token**:
|
||||
|
||||
- Ensure the `ADMIN_TOKEN` is a long, unique string to prevent unauthorized admin access.
|
||||
|
||||
---
|
||||
|
||||
## **Why Vaultwarden?**
|
||||
|
||||
- **Lightweight and Efficient**:
|
||||
|
||||
- Minimal system resource usage, ideal for home labs or low-spec servers.
|
||||
- **Self-Hosted Privacy**:
|
||||
|
||||
- Full control over your data without relying on third-party services.
|
||||
- **Feature-Rich**:
|
||||
|
||||
- Multi-user support, secure notes, 2FA, and API compatibility with Bitwarden clients.
|
||||
- **Cost-Effective**:
|
||||
|
||||
- No subscription fees or licensing costs.
|
||||
|
||||
---
|
||||
|
||||
## **Troubleshooting**
|
||||
|
||||
- **Container Won't Start**:
|
||||
|
||||
- Check logs:
|
||||
|
||||
```bash
|
||||
docker logs vaultwarden
|
||||
```
|
||||
|
||||
- Verify environment variables and network settings.
|
||||
- **Access Issues**:
|
||||
|
||||
- Ensure the correct domain or IP is used in the `DOMAIN` variable.
|
||||
- Verify firewall rules are not blocking the configured ports.
|
||||
- **Admin Panel Not Accessible**:
|
||||
|
||||
- Confirm the `ADMIN_TOKEN` is correctly set and retry.
|
||||
|
||||
---
|
||||
|
||||
Vaultwarden is a powerful, lightweight solution for self-hosting your password manager. By following this guide, you'll have a secure and reliable service tailored to your home lab environment.
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Patching
|
||||
---
|
||||
|
||||
|
||||
<iframe allowfullscreen="allowfullscreen" height="336" src="https://www.youtube.com/embed/1YMqkNv8HKQ" width="600"></iframe>
|
||||
|
||||
Watchtower has been on my list for a long time. I’ve avoided it because I was initially told it would just update all of my Docker containers automatically. I’m not one to do auto-update things. I like to read about it, understand the changes, and know if it's going to break anything before I update in 99% of the cases. Now, knowing that, I have rarely had breaking changes in containers, but it definitely does happen.
|
||||
|
||||
If you are someone who isn't averse to breaking changes, then you should consider letting Watchtower do it's thing full speed ahead. However, if you are like me, then you'll be happy to know that you can setup Watchtower to simply notify you when there are new versions of your docker images available, and you can then choose to update, or stay where you are.
|
||||
|
||||
## Pre-installation Setup
|
||||
|
||||
Watchtower Documentation: [https://containrrr.dev/watchtower/notifications/](https://containrrr.dev/watchtower/notifications/)
|
||||
|
||||
Before you run Watchtower, you need to decide a couple of things.
|
||||
|
||||
1. Do you want Watchtower to update your Containers automatically, or do you want to be notified of available updates only, or do you want Watchtower to completely ignore certain containers?
|
||||
2. Do you want to set the schedule on which Watchtower runs?
|
||||
3. How do you want to be notified?
|
||||
|
||||
For our setup today, we'll discuss all three options for update automatically, notify only, and ignore. We'll setup notifications via e-mail, and we'll set a schedule using the 6 position cron syntax. There are all things you need to have ready and prepared before running your Watchtower container, or you'll just have all of your containers updated automatically, and pretty much immediately.
|
||||
|
||||
### Update Options
|
||||
|
||||
If you want to update your containers automatically, you really only need the e-mail SMTP information (or notification setup info for your desired notification method), and if you want it, a schedule cron flag.
|
||||
|
||||
If, however, you want to be notified of available updated, but don't want the container to be auto-updated; or you simply want watchtower to ignore certain containers completely, you first need to re-create your containers with a new label.
|
||||
|
||||
I do this via Portainer (it's quite easy, and useful to use the Portainer GUI for this, but not necessary if you prefer the CLI). In Portainer, click on the container you want to set the label for, then click the 'Duplicate/Edit' button inside the container space in Portainer.
|
||||
|
||||
Now, scroll to the bottom, and click the 'Labels' tab. Add a new label for your preferred action:
|
||||
|
||||
#### Notify Only
|
||||
|
||||
Add the following as the label `com.centurylinklabs.watchtower.monitor-only` and then enter `true` as the value.
|
||||
|
||||
Now click the "Deploy the container" button, and confirm that you want to replace the existing container. This should bring up your container just as it was, and simply add a label to it that Watchtower will read, and know to only notify you if a new version of the image / container is available.
|
||||
|
||||
#### Ignore Container
|
||||
|
||||
Add the following as the label `com.centurylinklabs.watchtower.enable` and for the value enter `false`.
|
||||
|
||||
Now click the "Deploy the container" button, and confirm that you want to replace the existing container. This should bring up your container just as it was, and simply add a label to it that Watchtower will read, and know to ignore the container.
|
||||
|
||||
> It is EXTREMELY IMPORTANT that you setup the labels before running Watchtower if you don't want it to update all of your containers immediately.
|
||||
|
||||
### SMTP Setup
|
||||
|
||||
Next, in order to get notifications (whether in Notify Only, or for containers that have been updated), we'll setup our e-mail SMTP server information. You really set this, and the scheduling up in the Docker Run command for Watchtower, but it's valuable to get the information together before you enter the command.
|
||||
|
||||
<figure class="kg-card kg-code-card" id="bkmrk--e-watchtower_notifi">```
|
||||
-e WATCHTOWER_NOTIFICATIONS=email \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_FROM=fromaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_TO=toaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587 \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=fromaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=app_password \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2 \
|
||||
```
|
||||
|
||||
<figcaption>While I add this for convenience, it's always valuable to check the Official Watchtower site for up to date usage information.</figcaption></figure>FROM - your email address
|
||||
TO - your email address
|
||||
SERVER - your SMTP server (I generally recommend against Gmail due to difficulties in getting it to work, but feel free tot ry it).
|
||||
PORT - depends on your SMTP server / host
|
||||
USER - usually your full email address, but could be the part before the @ symbol, depends on your SMTP server / host
|
||||
PASSWORD - your email password
|
||||
|
||||
Leave the NOTIFICATIONS and DELAY values as they are.
|
||||
|
||||
### Cron for Scheduling the Checks
|
||||
|
||||
Watchtower uses a 6 position cron syntax to schedule the checks.
|
||||
|
||||
```
|
||||
* * * * * *
|
||||
s m h D W M
|
||||
s = seconds
|
||||
m = minutes
|
||||
h = hours
|
||||
D = Days
|
||||
W = Weeks
|
||||
M = Months
|
||||
```
|
||||
|
||||
So, we can set our schedule in many ways. I messed up and misunderstood when I did the video, and initially set it to run every 5 seconds. Don't do that...trust me!
|
||||
|
||||
Let's say we want to run every hour of every day:
|
||||
|
||||
```
|
||||
0 0 * * * *
|
||||
```
|
||||
|
||||
This will run every hour.
|
||||
|
||||
I run mine every day with
|
||||
|
||||
```
|
||||
0 0 0 */1 * *
|
||||
```
|
||||
|
||||
If you want to run every week you could change it to:
|
||||
|
||||
```
|
||||
0 0 0 * */1 *
|
||||
```
|
||||
|
||||
And so on.
|
||||
|
||||
## Install Watchtower
|
||||
|
||||
Now that we have all of our information together, we can install Watchtwoer and get it running confidently.
|
||||
|
||||
We'll use this command:
|
||||
|
||||
```
|
||||
docker run -d \
|
||||
--name watchtower \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e WATCHTOWER_NOTIFICATIONS=email \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_FROM=fromaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_TO=toaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587 \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=fromaddress@gmail.com \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=app_password \
|
||||
-e WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2 \
|
||||
-e WATCHTOWER_SCHEDULE="0 0 0 */1 * *"
|
||||
containrrr/watchtower
|
||||
```
|
||||
|
||||
of course filling in your appropriate Email information in the fileds shown.
|
||||
|
||||
Press Enter / return, and let it run.
|
||||
|
||||
You should see watchtower startup, and you can verify it's running in Portainer, or via the `docker ps` command.
|
||||
|
||||
You can also check the logs in Portainer, or via the `docker logs watchtower` command.
|
||||
|
||||
It should also send an immediate email (or within a few minutes). Once you have it, you'll know things are probably setup correctly.
|
||||
|
||||
Just sit back and wait for the updates, and notifications.
|
||||
|
||||
# Watchtower Service Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
**Watchtower** is a lightweight and powerful tool designed to automate the process of keeping Docker containers up-to-date. By monitoring the Docker socket, Watchtower checks for updates to container images, pulls the latest versions, and restarts the containers with minimal intervention. This automation is especially useful in home lab environments or production setups, reducing the need for manual updates and ensuring containers remain secure and current.
|
||||
|
||||
---
|
||||
|
||||
## Key Features
|
||||
|
||||
1. **Automated Updates**: Automatically checks for and applies updates to running containers.
|
||||
2. **Scheduled Checks**: Allows for configurable schedules to avoid disruption during peak usage times.
|
||||
3. **Resource Optimization**: Cleans up outdated images after updates to conserve disk space.
|
||||
4. **Ease of Use**: Minimal setup and configuration required for seamless integration with Docker.
|
||||
|
||||
---
|
||||
|
||||
## Docker Compose Configuration
|
||||
|
||||
Here’s the `docker-compose.yml` file for deploying Watchtower:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
||||
watchtower:
|
||||
|
||||
image: containrrr/watchtower
|
||||
container_name: 'watchtower'
|
||||
restart: 'unless-stopped'
|
||||
environment:
|
||||
TZ: America/New_York
|
||||
WATCHTOWER_CLEANUP: true
|
||||
WATCHTOWER_INCLUDE_RESTARTING: true
|
||||
WATCHTOWER_ROLLING_RESTARTING: true
|
||||
WATCHTOWER_SCHEDULE: "0 0 4 * * *"
|
||||
WATCHTOWER_INCLUDE_STOPPED: true
|
||||
WATCHTOWER_NOTIFICATIONS: email
|
||||
WATCHTOWER_NOTIFICATIONS_HOSTNAME: "Docker Server"
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_FROM: miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_TO: miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER: mail.mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: "password"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- command: --cleanup --schedule "0 3 * * *"
|
||||
```
|
||||
|
||||
### Configuration Explanation
|
||||
|
||||
1. **Image**:
|
||||
The `containrrr/watchtower` image is the official Watchtower image, ensuring reliability and access to the latest features.
|
||||
|
||||
2. **Container Name**:
|
||||
Naming the container `watchtower` simplifies management and identification in your Docker environment.
|
||||
|
||||
3. **Restart Policy**:
|
||||
The `restart: unless-stopped` policy ensures that Watchtower stays active and restarts automatically after reboots or crashes.
|
||||
|
||||
4. **Volumes**:
|
||||
|
||||
- **`/var/run/docker.sock`**: Provides Watchtower access to Docker's API, enabling it to monitor and manage other containers.
|
||||
5. **Command**:
|
||||
|
||||
- `--cleanup`: Automatically removes outdated images after successful updates to save storage space.
|
||||
- `--schedule "0 3 * * *"`: Configures Watchtower to check for updates daily at 3:00 AM UTC, a time chosen to minimize impact on regular operations.
|
||||
|
||||
---
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
1. **Save the Configuration**:
|
||||
Save the provided `docker-compose.yml` file to a directory of your choice.
|
||||
|
||||
2. **Deploy the Service**:
|
||||
Start the Watchtower service with the following command:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
3. **Verify the Deployment**:
|
||||
Check that Watchtower is running:
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
4. **Monitor Logs**:
|
||||
Review the logs to ensure that Watchtower is functioning as expected:
|
||||
|
||||
```bash
|
||||
docker logs watchtower
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Docker Socket Access**:
|
||||
The Docker socket grants full access to the Docker API. Restrict access to the Docker host to trusted users and monitor logs for unusual activity.
|
||||
|
||||
- **Backup Before Updates**:
|
||||
While Watchtower is reliable, always maintain backups of critical containers and data to mitigate risks associated with updates.
|
||||
|
||||
- **Testing in Staging**:
|
||||
If possible, test updates in a staging environment before applying them to production systems.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Benefits of Using Watchtower
|
||||
|
||||
- **Efficiency**: Automates repetitive update tasks, saving time and effort.
|
||||
- **Reliability**: Ensures containers are consistently running the latest and most secure versions.
|
||||
- **Resource Optimization**: Prevents outdated images from consuming unnecessary storage space.
|
||||
- **Convenience**: Minimal configuration required for ongoing maintenance of your Docker environment.
|
||||
|
||||
---
|
||||
|
||||
## Advanced Options
|
||||
|
||||
- **Excluding Containers**:
|
||||
You can exclude specific containers from being updated by adding the `com.centurylinklabs.watchtower.enable` label set to `false` in their configurations:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=false"
|
||||
```
|
||||
|
||||
- **Notification Integrations**:
|
||||
Configure Watchtower to send update notifications to services like Slack, email, or webhooks for better monitoring:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
WATCHTOWER_NOTIFICATIONS: "slack"
|
||||
WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL: "<your-slack-webhook-url>"
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
By integrating Watchtower into your home lab or production environment, you can maintain an up-to-date and secure container ecosystem with minimal manual intervention. It’s a set-it-and-forget-it tool that streamlines container management, allowing you to focus on other aspects of your infrastructure.
|
||||
@@ -0,0 +1,347 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Monitoring
|
||||
---
|
||||
|
||||
|
||||
UPDATED: June 6, 2024 with newer instructions
|
||||
|
||||
I've been asked about Zabbix for a while now. I have covered some other solutions for monitoring equipment / services in the past. CheckMK, using Dashy Widgets, Glances, NetData, and several others are some really great options for monitoring, and as with any software, the right thing for you will depend greatly on your needs. As I started looking at Zabbix, I was contacted by Marc over at [OneMarcFifty](https://www.youtube.com/c/OneMarcFifty?app=desktop "OneMarcFifty Channel") about doing a collaborative video series with him on Zabbix. He asked if I would be interested in covering the install, and he would cover some more in-depth setup of getting monitored systems enrolled, as well as setting up email alerts for anything the system finds.
|
||||
|
||||
How could I say, "No" to such a great opportunity? Of course I was interested. Marc does some absolutely amazing content, and I have watched his channel for a couple of years now. He has some incredibly great content on all kinds of tech topics, and his explanations are just terrific, so definitely jump over to his channel for the second part of this tutorial once you've got Zabbix up and running. You can find the video right here.
|
||||
|
||||
### Installation
|
||||
|
||||
#### What you'll need
|
||||
|
||||
* A system with Docker-CE and Docker-Compose installed (we'll call this the Host Server for this tutorial)
|
||||
* SSH Access to the Host Server
|
||||
* Git, Curl, Wget installed on the Host Server
|
||||
* About 30 Minutes of your time
|
||||
|
||||
### Installation of Docker via a Simple Script
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget -O install-docker.sh <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install-docker.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install-docker.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install. In this case, you really only need to install Docker-CE and Docker-Compose. Feel free to answer 'n' to the other software options.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of sudo in front of them.
|
||||
|
||||
Alternatively, you can try the following commands:
|
||||
|
||||
`newgrp`
|
||||
|
||||
`newgrp docker`
|
||||
|
||||
Now you can test your ability to run a docker command by doing
|
||||
|
||||
`docker ps`
|
||||
|
||||
If you don't get any errors, you are good to go.
|
||||
|
||||
### Installing Zabbix
|
||||
|
||||
Now that we have our server software setup, we'll start on our Zabbix installation. Fortunately, Zabbix provides a nice set of ready to use docker-compose options for us. We'll clone the Zabbix-Docker repository from github, and then make a few modifications to some specific files to set our Environment Variables, and then we'll be ready to run.
|
||||
|
||||
First, we need to make sure we have git, curl, and wget installed on our Host Server. We can install them on Debian / Ubuntu with
|
||||
|
||||
`sudo apt install git curl wget -y`
|
||||
|
||||
On Fedora, CentOS, Redhat we should be able to use:
|
||||
|
||||
`sudo dnf install git curl wget -y`
|
||||
|
||||
On Arch, you should be able to use
|
||||
|
||||
`sudo pacman -S git curl wget`
|
||||
|
||||
For OpenSuse, you should use
|
||||
|
||||
`sudo zypper install get curl wget`
|
||||
|
||||
Once those few dependencies are installed, we'll use the git command to pull down the Zabbix-Docker repository to our local machine. First, however, let's move into the "docker" folder. If you don't already have a top level folder to keep all of your docker applications in, I highly recommend you set one up, as you can then simply compress and backup the top level folder and have all of your docker applications and data backed up with one command.
|
||||
|
||||
`cd docker`
|
||||
|
||||
Now let's clone that repository:
|
||||
|
||||
`git clone` [`https://github.com/zabbix/zabbix-docker.git`](https://github.com/zabbix/zabbix-docker.git)
|
||||
|
||||
This will create a folder called "zabbix-docker" with all of the files from the repository in it. We'll move into that folder with
|
||||
|
||||
`cd zabbix-docker`
|
||||
|
||||
In this folder you'll find many docker-compose template files. These are labeled in a way that is fairly easy to understand. Each file that has "local" in the name, means that the compose file will attempt to build new images when run, versus the files that only have "latest" and not "local" in the name. These files will pull down pre-built images from dockerhub for us to use in our system.
|
||||
|
||||
In this updated version we'll be using the three files labeled "compose.yaml", "compose\_databases.yaml", and "compose\_zabbix\_components.yaml".
|
||||
|
||||
Next, we need to set a few environment variables. These variables are super useful, especially in large projects like Zabbix, because you can set a value one time, and it is reused throughout the project. This reduces issues with misspellings, mimatched values throughout a docker-compose file, etc.
|
||||
|
||||
We'll move into the environment variable folder of the project with the command:
|
||||
|
||||
`cd env_vars`
|
||||
|
||||
In this folder, are a group of hidden files. In Linux / Unix based systems, hidden files are set by the use of a dot / period in front of the file name. In order to see these files in our directory we use the flag "a" with the "ls" command. We can also use the flag "l" to list out the file permissions, and make them list vertically down the screen. So, let's list out the files:
|
||||
|
||||
`ls -al`
|
||||
|
||||
We need to set a few variables. Most of these files we will leave untouched, however.
|
||||
|
||||
First, we'll edit the following files since we are using the mysql version of the docker-compose they provide.
|
||||
|
||||
* MYSQL\_PASSWORD
|
||||
* MYSQL\_ROOT\_PASSWORD
|
||||
|
||||
We don't need to change the POSTGRES\_PASSWORD, POSTGRES\_USER values unless you prefer to use Postgres DB, in which case change the password file at the very least.
|
||||
|
||||
In order to edit each file, you'll use the following command structure:
|
||||
|
||||
`nano <filename including the leading dot ".">`
|
||||
|
||||
Make the change to the value, then save using CTRL+O, then Enter to confirm, and CTRL+X to exit the nano editor.
|
||||
|
||||
We'll use the .MYSQL\_PASSWORD as our first example:
|
||||
|
||||
`nano .MYSQL_PASSWORD`
|
||||
|
||||
You should then see this following
|
||||
|
||||
`zabbix`
|
||||
|
||||
Which you'll change to a long password (32 characters or more) with upper and lower case characters and numbers all mixed in.
|
||||
|
||||
Then save, with CTRL+O, and Enter to confirm, then CTRL+X to exit the nano editor.
|
||||
|
||||
Repeat this process for the .MYSQL\_ROOT\_PASSWORD as well, using a different password.
|
||||
|
||||
Next, we may want to make a change in a couple of the other files in this directory. I make a few modifications in the video, but they are not necessary. If you want to make changes, be certain you understand how those changes effect the system overall.
|
||||
|
||||
For instance, in the "compose\_zabbix\_components.yaml" file, I need / want to change the web-nginx port mappings, because it is set to 8080 and 8443 on the host be default, and I'm already running an application (Zammad) that uses these ports on the host.
|
||||
|
||||
You can see if your port 8080 is being used on your host by running the command
|
||||
|
||||
`sudo lsof -i -P -n | grep LISTEN`
|
||||
|
||||
and look at the ports listed. Each port listed is already in use on the system.
|
||||
|
||||
To change the ports, you can do
|
||||
|
||||
`nano compose_zabbix_components.yaml`
|
||||
|
||||
Once in the file, use the CTRL + W hotkey combo to open the search feature. Then, type in 'web-nginx' and hit Enter to search.
|
||||
|
||||
When you reach the web-nginx section, look for the 'ports:' sub-section and edit the left side of the port mapping. It will be a long string of text surrounded by curly braces.
|
||||
|
||||
```yaml
|
||||
web-nginx:
|
||||
ports:
|
||||
- "${ZABBIX_WEB_NGINX_HTTP_PORT}:8080"
|
||||
- "${ZABBIX_WEB_NGINX_HTTPS_PORT}:8443"
|
||||
```
|
||||
|
||||
Replace `${ZABBIX_WEB_NGINX_HTTP_PORT}` with a port number not in use on your machine, and above 8000 preferably. I used 8052 for mine. You can also replace `${ZABBIX_WEB_NGINX_HTTPS_PORT}` with a port number if you wish, I used 9043.
|
||||
|
||||
When done my section looked like this:
|
||||
|
||||
```
|
||||
web-nginx:
|
||||
ports:
|
||||
- "$8052:8080"
|
||||
- "9043:8443"
|
||||
```
|
||||
|
||||
Save your changes with CTRL + O, then press Enter to confirm, and use CTRL + X to exit the nano editor.
|
||||
|
||||
Once, you've made changes to the necessary environment variables and ports, we are ready to run our docker-compose.yml file.
|
||||
|
||||
Now we can run:
|
||||
|
||||
`docker-compose up -d && docker-compose logs -f`
|
||||
|
||||
Be patient. The initial startup takes a good bit. I'd say as long as you don't see any errors, let it run. Go get some coffee, or just chill on YouTube watching the AwesomeOpenSource channel for a bit.
|
||||
|
||||
This really runs two commands: The part before the "&&" will pull down the zabbix images, and create new containers for us. The part after the "&&" will show us the logs of Zabbix starting up after the containers are started.
|
||||
|
||||
You may see some warnings in the logs about the limitation settings for CPU, Memory, etc. This is because docker-compose is not an orchestrator. In docker-compose v3 and later, the limit values are ignored. Such values are used in docker-swarm only.
|
||||
|
||||
This is a minimal startup of the base services needed to start up Zabbix server and be able to connect external clients to it. But there are many more services that can be started up. I show this in the video. Once you've started Zabbix successfully, setup your reverse proxy for a fully qualified domain name (FQDN), and have https working for your site, we can start these other services.
|
||||
|
||||
To start them, we'll go back to the terminal and enter the command:
|
||||
|
||||
`docker compose --profile all pull`
|
||||
|
||||
This will pull down several more images to be used in our server, including the dockerized version of the agent, so we can monitor our docker based Zabbix server.
|
||||
|
||||
Once those have all pulled down, we'll start them up (without having to stop anything that's already running) by doing the command:
|
||||
|
||||
`docker compose --profile all up -d`
|
||||
|
||||
You'll see the new containers being started up, be patient while everything starts. This can all take a while, an dit's especially hardware and resource dependent.
|
||||
|
||||
Once started, you should be able to do:
|
||||
|
||||
`docker compose ps`
|
||||
|
||||
and see a whole list of running containers on your system.
|
||||
|
||||
Next we need to setup the agent container to be able to talk to the server container, and get it setup as Host in Zabbix. Check out the video on how to setup a Host through the Zabbix Web UI, but I'll give you the commands to use for getting the right information from the two containers, here, as it's a bit more involved.
|
||||
|
||||
#### Setting Up the Zabbix Container Agent to Monitor the Zabbix Container Server
|
||||
|
||||
First, we need a couple of IP addresses from our containers. In particular, you'll want the one from the zabbix-agent container, and the zabbix-server container. We can get these by using a couple of docker commands. First, we'll list out our containers with
|
||||
|
||||
`docker ps`
|
||||
|
||||
This will show us all of our running containers. We are really interested only in the ones with zabbix in the name. Find the container called "zabbix-docker-zabbix-server-1", and then locate it's container id, and highlight and copy it. You can right click and select "Copy", or use CTRL + Shift + C in the terminal to copy.
|
||||
|
||||
now, enter
|
||||
|
||||
`docker inspect <id you just copied>`
|
||||
|
||||
It should look something like
|
||||
|
||||
`docker inspect 8cf2731bef1d`
|
||||
|
||||
It's worth noting, your ID will be different.
|
||||
|
||||
When you get the output of the inspect command, at the end will be a segment for network information. There you'll see a key for the ip address of this container inside the docker network. We need that address.
|
||||
|
||||
You should see some information like this:
|
||||
|
||||
```json
|
||||
"zabbix-docker_frontend": {
|
||||
"IPAMConfig": null,
|
||||
"Links": null,
|
||||
"Aliases": [
|
||||
"zabbix-docker-zabbix-server-1",
|
||||
"zabbix-server"
|
||||
],
|
||||
"MacAddress": "02:42:ac:10:ee:03",
|
||||
"NetworkID": "fd61396dda648b01b00a4f23d2640577823230923e8b25d71bf1b2339ac",
|
||||
"EndpointID": "ef3a483717dc831856d9f14gnei48vansu74ifj439afjaf7766e5ffe810389e9315",
|
||||
"Gateway": "172.16.239.1",
|
||||
"IPAddress": "172.16.239.3",
|
||||
"IPPrefixLen": 24,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"DriverOpts": null,
|
||||
"DNSNames": [
|
||||
"zabbix-docker-zabbix-server-1",
|
||||
"zabbix-server",
|
||||
"8cf2722bef1d"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
We need the IP address listed here as `"IPAddress": "172.16.239.3",`.
|
||||
|
||||
We need to do the same thing for our container "zabbix-docker-zabbix-agent-1". Get the ID, do the docker inspect on the ID, and grap it's IPAddress value from the JSON output.
|
||||
|
||||
You should put these somewhere so you can grab them quickly again. I made a simple text file, and marked them as
|
||||
|
||||
Agent IP: 172.16.239.6
|
||||
ServerIP: 172.16.239.3
|
||||
|
||||
Now we need to jump into the agent docker container, and edit a file that will tell the agent where to communicate with the server.
|
||||
|
||||
`docker exec -it zabbix-docker-zabbix-agent-1 /bin/bash`
|
||||
|
||||
This will get you into the container at a new command prompt. From here we'll edit our file located at /etc/zabbix/zabbix\_agentd.conf
|
||||
|
||||
To do this, we'll have to use the VI editor, as the container does not have nano installed, but no big deal.
|
||||
|
||||
`vi /etc/zabbix/zabbix_agentd.conf`
|
||||
|
||||
Now, press the 'i' key on the keyboard, to go into 'insert' mode in VI. Scroll down to the section where you'll see a line that says
|
||||
|
||||
`SourceIP=127.0.0.1`
|
||||
|
||||
Remove the '127.0.0.1' and replace it with the agent IP that we got earlier.
|
||||
|
||||
`SourceIP=172.16.239.6`
|
||||
|
||||
Next, we'll scroll down until we see a section for the 'Server'.
|
||||
|
||||
```bash
|
||||
### Option: Server
|
||||
# List of comma delimited IP addresses, optionally in CIDR notation, or DNS names of Zabbix servers and Zabbix proxies.
|
||||
# Incoming connections will be accepted only from the hosts listed here.
|
||||
# If IPv6 support is enabled then '127.0.0.1', '::127.0.0.1', '::ffff:127.0.0.1' are treated equally
|
||||
# and '::/0' will allow any IPv4 or IPv6 address.
|
||||
# '0.0.0.0/0' can be used to allow any IPv4 address.
|
||||
# Example: Server=127.0.0.1,192.168.1.0/24,::1,2001:db8::/32,zabbix.example.com
|
||||
#
|
||||
# Mandatory: yes, if StartAgents is not explicitly set to 0
|
||||
# Default:
|
||||
# Server=
|
||||
|
||||
Server=zabbix-server
|
||||
```
|
||||
|
||||
We want to remove 'zabbix-server' and instead enter the IP address for the server we copied.
|
||||
|
||||
`Server=172.16.239.3`
|
||||
|
||||
Next, we want to do the exact same thing for the 'ServerActive' section just a little bit down from the 'Server' section.
|
||||
|
||||
`ServerActive=zabbix-server:10051`
|
||||
|
||||
We want to remove 'zabbix-server:10051' and enter the Server IP we copied, again.
|
||||
|
||||
`ServerActive=172.16.239.3`
|
||||
|
||||
Now we can save by pressing the escapte key, Esc, to exit insert mode. Then, we need to type `:wq` which tells VI to write (save) the changes, and (q)uit out of VI.
|
||||
|
||||
Now we are back at the prompt inside our agent container, so let's type `exit` and leave our container area, and we'll be back at our normal prompt.
|
||||
|
||||
We'll restart the agent with
|
||||
|
||||
`docker restart zabbix-docker-zabbix-agent-1`
|
||||
|
||||
Give it a minute or so, and go back to your Zabbix Server Web UI, and you should see that the server host has been updated (this assumes you've gone in the Web UI and changed the IP address in the host entry under the Monitoring menu). You need to change the IP from 127.0.0.1 in the Host entry, to be the IP of the agent you copied earlier. Save / Update that host, and give it a minute.
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
One issue I came across during my testing of how to get all of this up and running, was that on one of my servers, my docker-compose version was not new enough. It would continuously give me an error about "profiles" not being supported. The key is to get a newer version of docker-compose installed. Depending on the version of your Linux Distribution, you may have to add a more recent repository in order to update your docker-compose version, or do more of a manual install of docker-compose. Since there are so many variables on what OS may need which setup, it's not feasible for me to try and guide you further on the topic. I ended up on docker-compose version 1.29.x and it worked without issue. ON 1.25.x I was getting the issue with the "profiles" section of the docker-compose file.
|
||||
|
||||
#### The Zabbix Web Interface
|
||||
|
||||
You should now be able to access the Zabbix Web Interface using your web browser of choice. You'll go to the IP address of your host machine. In my case I installed it on a machine with the IP 192.168.10.42. So in my web browser I type:
|
||||
|
||||
[http://192.168.10.42](http://192.168.10.42)
|
||||
|
||||
If you changed the 80:8080 port mapping, make sure to add the port to your IP. If I had change it from 80:8080 to 8022:8080, I would then enter the following into my browser url bar:
|
||||
|
||||
[http://192.168.10.42:8022](http://192.168.10.42:8022)
|
||||
|
||||
Once you see the login page (be patient, as it could take a few minutes for Zabbix to come up the first time), use the username "Admin" and password "zabbix" to login.
|
||||
|
||||
You should immediately navigate to the User Settings >> Profile in the left navigation bar to change your admin user password to a long, strong password.
|
||||
|
||||
You are now ready to begin enrolling devices into your Zabbix monitoring solution. This is a massive system with an incredible amount of power. Take your time, get to know what all it's capable of doing, and what information you can gain from it. A system like this is worth the time you'll put into making it do as much as you can.
|
||||
|
||||
In the video, I go through setting up one client machine. It's a manual process, but worth watching. Make sure to watch Marc's follow up video over [@OneMarcFifty](https://www.youtube.com/c/OneMarcFifty?app=desktop) where he will help you unlock more of the power available in this awesome open source system.
|
||||
|
||||
#### Support My Channel and Content
|
||||
|
||||
{{@19#bkmrk-support-my-channel-a-0}}
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Wireguard
|
||||
---
|
||||
|
||||
|
||||
<iframe allowfullscreen="allowfullscreen" height="336" src="https://www.youtube.com/embed/BRLB4wRL4cM" width="600"></iframe>
|
||||
|
||||
WG-Easy is essentially exactly what it sounds like. It's a containerized setup that includes a web user interface intended to make setting up a Wireguard network as easy as possible. Well, it pretty much lives up to its name. The setup of the server is very straight-forward, and the web user interface is very easy to use once everything is up and running. Adding devices, using the native Wireguard clients on each OS is also a breeze.
|
||||
|
||||
### What You'll Need
|
||||
|
||||
- A machine to act as a server with Docker-CE and Docker Compose installed
|
||||
- Wireguard tools installed and a Linux Kernel with Wireguard installed
|
||||
- A Public IP address
|
||||
- (Optional) A domain or subdomain for your server
|
||||
- (Optional) a Reverse Proxy
|
||||
- Access to open ports 51820 and 51821 on your firewall for the server
|
||||
- About 10 minutes of your time.
|
||||
|
||||
### Install
|
||||
|
||||
I used a Digital Ocean droplet to setup my server. The benefit here is that I get a public IP address and a virtual appliance type firewall in front of that server. Full discolsure, I have an [affiliate link for Digital Ocean](https://m.do.co/c/a6a61ae55242 "Link for $ 50.00 Credit on Digital Ocean"). If you use that link, you'll get a $ 50.00 credit for 60 days to test out Digital Ocean. The VPS I setup cost only $6.00 / month. So you could setup a lot of servers in 60 days to try out. If you stay with them and become a paying customer, I'll get a credit as well. If you don't, I don't.
|
||||
|
||||
### Installation of Docker-CE and Docker Compose via a Simple Script
|
||||
|
||||
You can easily install Docker-CE, Docker-Compose, Portainer-CE, and NGinX Proxy manager by using this quick install script I created and maintain on Github. Just use the command:
|
||||
|
||||
`wget -O install-docker.sh <a href="https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh">https://gitlab.com/bmcgonag/docker_installs/-/raw/main/install_docker_nproxyman.sh</a>`
|
||||
|
||||
To download the script to your desired host.
|
||||
|
||||
Change the permissions to make the script executable:
|
||||
|
||||
`chmod +x ./install-docker.sh`
|
||||
|
||||
and then run the script with the command:
|
||||
|
||||
`./install-docker.sh`
|
||||
|
||||
When run, the script will prompt you to select your host operating system, then will ask you which bits of software you want to install.
|
||||
|
||||
Simply enter 'y' for each thing you want to install. In this case we definitely want Docker-CE and Docker Compose. You can optionally elect to install and setup NGinX Proxy Manager if desired.
|
||||
|
||||
At some point, you may be asked for your super user (sudo) password as well.
|
||||
|
||||
Allow the script to complete installation.
|
||||
|
||||
At this point, you might want to log out and back in, as this will allow you to use the `docker` and `docker-compose` commands without the need of sudo in front of them.
|
||||
|
||||
### Installing WG-Easy
|
||||
|
||||
WG-Easy is really a straight forward setup. First, let's create the folder structure we want on our server. I always like to create a parent docker folder, and inside that parent folder, create a folder for each application I'll be running. This makes it easy to update applications as needed, as well as backing them up by zipping up the parent 'docker' folder, and copying that zipped version off to my backup servers. Let's create our folders now, with one simple command:
|
||||
|
||||
`mkdir -p docker/wg-easy`
|
||||
|
||||
Now, we'll move into our foldeer and create a new file called "docker-compose.yml":
|
||||
|
||||
`cd docker/wg-easy`
|
||||
|
||||
`nano docker-compose.yml`
|
||||
|
||||
Now that we are inside our "docker-compose.yml" file, we'll add the code block below to it. Then, you'll want or need to change a couple of the variables quickly to make sure that you have everything ready to go.
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
wg-easy:
|
||||
container_name: wg-easy
|
||||
environment:
|
||||
- LANG=en
|
||||
- WG_HOST=<your ip or domain name here>
|
||||
- PASSWORD=<a-long-str06-pa5sw0rD-Her3>
|
||||
volumes:
|
||||
- ./wg-easy:/etc/wireguard
|
||||
ports:
|
||||
- 51820:51820/udp
|
||||
- 51821:51821/tcp
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
sysctls:
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
- net.ipv4.ip_forward=1
|
||||
restart: unless-stopped
|
||||
image: ghcr.io/wg-easy/wg-easy
|
||||
```
|
||||
|
||||
In the file you just copied and pasted, change any of the values inside the less than "<" and greater than ">" symbols. For WG\_HOST you can use either the IP address of the host server, or the domain / subdomain for the server. To use the domain / sub-domain you need to have an A-record pointing the domain / sub-domain pointing to your server's public IPv4 address.
|
||||
|
||||
Enter a really good, long strong password for the PASSWORD entry, and optionally you can change the left side of the port mappings if needed, but usually 51820 and 51821 should be free if you haven't already setup a wireguard server on this same machine.
|
||||
|
||||
Save the file with CTRL + O, then press Enter to confirm. Exit the nano editor with CTRL + X.
|
||||
|
||||
<p class="callout info">Don't forget to setup your A-record if using a domain / sub-domain, and additionally, setup your reverse proxy if using a reverse proxy for the web UI. The port for accessing the Web UI is 51821.</p>
|
||||
|
||||
Now, let's startup our server. We'll use two commands on one line:
|
||||
|
||||
`docker compose up -d && docker compose logs -f`
|
||||
|
||||
The first part of the command tells docker compose to start the service running. The second part tells docker compose to show us the running log out put after the service is started. Here we can look for any errors or other issues we may need to address. If you don't see any errors, just use CTRL + C to exit the logging.
|
||||
|
||||
In your favorite modern browser go to either the IPv4 address and port 51821, or your domain and port 51821, or if you've setup a reverse proxy like I did in the video, the domain.
|
||||
|
||||
You should be greeted with a Login prompt asking for your password. This is the PASSWORD value you put in the docker-compose.yml file.
|
||||
|
||||
Once logged in, you can create a new configuration for your first device. ONce named, and created, you can use the QR code to scan with the Wireguard app on your mobile device, or download the config using the download icon for your desktops and servers.
|
||||
|
||||
On Linux, you want to make sure you have Wireguard and Wireguard tools installed an ready. Use wg-quick to bring your devices up and down, or find a suitable desktop tool with a UI to do this with.
|
||||
|
||||
You'll see when a device is connected in the server, and see when it has traffic flowing as well.
|
||||
|
||||
congratulations, you've setup WG-Easy and are ready to start using it for private, secure tunneled traffic all over the internet.
|
||||
|
||||
### Support My Channel and Content
|
||||
|
||||
|
||||
Support my Channel and ongoing efforts through Patreon:
|
||||
[https://www.patreon.com/awesomeopensource](https://www.patreon.com/bePatron?u=234177)
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
tags:
|
||||
- Docker
|
||||
- Manager
|
||||
- Email
|
||||
---
|
||||
Hestia Control Panel Setup
|
||||
|
||||
** 1. Change to sudo **
|
||||
|
||||
sudo su -
|
||||
|
||||
** 2. Get the install script **
|
||||
|
||||
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
|
||||
|
||||
|
||||
** 3. Important - CHANGE THE NEXT LINE TO USE YOUR OWN DETAILS, recommend using a subdomain like 'hcp' for your panel as I've done here **
|
||||
bash hst-install.sh --interactive no --email admin@mcfetridge.us --password S>>>>>>>>123 --hostname hcp.mcfetridge.us -f
|
||||
|
||||
** Make sure to capture this information
|
||||
Ready to get started? Log in using the following credentials:
|
||||
|
||||
Admin URL: https://hcp.mcfetridge.us:8083
|
||||
Backup URL: https://129.213.145.20:8083
|
||||
Username: admin
|
||||
Password: The password you chose during installation. My Default = S>>>>>>>>123
|
||||
|
||||
Sendblue SMTP key for HCP: xsmtpsib-1d075358c732f0ae42994d033cd552a43b867e08ddf1057f2414dec226c34ecc-UP2QRnLwmZvB7N3V
|
||||
|
||||
SMTP Server: smtp-relay.brevo.com
|
||||
Port: 587
|
||||
Login: mmcfetridg@aol.com
|
||||
Password: Is the smtp key generated.
|
||||
|
||||
For a smoother setup you can point the subdomain for your hostname over to the Oracle public IP address. In our video we used Namecheap, but all domain hosts will have a similar setup.
|
||||
|
||||
After installing, the ports you’ll need to add to your ingress rules are here:
|
||||
|
||||
8083,80,443,143,993,110,995,25,465,587
|
||||
|
||||
|
||||
|
||||
Blog: https://ideaspot.com.au/blog/cloudflare-hestia-setup/
|
||||
YouTube: https://www.youtube.com/watch?v=BK7qyPa-VmI
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
tags:
|
||||
- Desktop
|
||||
- Backup
|
||||
---
|
||||
- Install rclone on your linux desktop.
|
||||
- mkdir OneDrive (pick a location - I prefer the Documents directory)
|
||||
- run "rclone config" - Follow the screen prompts
|
||||
|
||||
When done Mount OneDrive
|
||||
- rclone --vfs-cache-mode writes mounts OneDrive: /home/miker/Documents/OneDrive &
|
||||
|
||||
This has to be place in a scripts and ran every time you boot your laptop.
|
||||
Reference in New Issue
Block a user