Compare commits

...

46 Commits

Author SHA1 Message Date
e3d3ade4f7 Update build-certs to use verbose logging 2025-11-23 18:39:57 -06:00
b41ad62aa1 Add mail and update gitea to use authelia sso 2025-11-23 18:38:26 -06:00
0566bf8a2d Change policy to only apply to servarr 2025-11-23 18:37:27 -06:00
46344bf719 Split authelia config so secrets aren't in repo 2025-11-23 13:25:07 -06:00
e417287103 Add template auth secrets 2025-11-23 00:18:19 -06:00
194173c32e Add second authelia config file 2025-11-23 00:10:14 -06:00
57d6021be3 Add memos service 2025-11-22 23:41:43 -06:00
d6f05752a6 Fix startup issues 2025-11-22 23:37:51 -06:00
dd34d0ab22 Add tftp server 2025-10-11 09:07:31 -05:00
698f16c819 Fix karakeep CSP to allow full-page archives to work properly 2025-10-08 00:52:11 -05:00
80f278a74c Use nginx variable to build CSP 2025-10-08 00:45:42 -05:00
816cca7f4f Add allows for data: urls in the CSP 2025-10-08 00:36:32 -05:00
60a0239682 Fix container naming 2025-10-04 16:54:36 -05:00
70c14f241e Add musl rustup runner 2025-10-04 16:20:10 -05:00
756049f74e Add qbt dependency on vpn 2025-09-30 11:31:29 -05:00
d4e6c7b732 Remove port publishing from qbt as well 2025-09-30 11:27:47 -05:00
8076a49199 Remove networks config from qbt 2025-09-30 11:23:33 -05:00
ba9d3d292c Add VPN config 2025-09-30 11:22:40 -05:00
3ac2b710ba Fix gpodder port 2025-09-27 01:37:24 -05:00
4d4289670e Add necessary env key 2025-09-27 01:31:49 -05:00
865c02a3a4 Add gpodder-rs setup 2025-09-27 01:15:39 -05:00
64ea7cb6e6 Add systemd and host act_runner to readme
Some checks are pending
Deploy homelab / Deploy (push) Waiting to run
2025-09-24 23:18:20 -05:00
2bf9ef29ac Add systemd units to run actions and homelab 2025-09-24 23:03:40 -05:00
b66697d924 Add gpodder nginx site 2025-09-24 23:03:20 -05:00
b9cccf5c50 Add gpodder to certs 2025-09-24 23:02:01 -05:00
a989f41f08 Add gitea runner dependency on gitea to docker compose 2025-09-24 22:05:07 -05:00
9ba1c58b95 Minor updates to match current homelab 2025-09-24 22:02:21 -05:00
742e64cfec Add notes for ZFS setup 2025-09-23 21:20:30 -05:00
fa7afb2a90 Add some vars for modded MC 2025-09-23 21:20:25 -05:00
06cd490f34 Fix issues and limit log size
All checks were successful
Deploy homelab / Deploy (push) Successful in 14s
2025-09-07 15:18:47 -05:00
f5b78e31b6 Adjust gitea repo and versions, to allow migration off latest
Some checks failed
Deploy homelab / Deploy (push) Failing after 3s
2025-09-06 03:58:06 -05:00
8c75d0fcda Pin ollama to specific version to avoid frequent restarts
All checks were successful
Deploy homelab / Deploy (push) Successful in 1s
2025-09-06 03:41:34 -05:00
7bb8ef4567 Update workflow file to match expected format 2025-09-06 03:41:14 -05:00
9e149fe667 Update gitea to nightly
All checks were successful
Deploy homelab / Deploy (push) Successful in 1m24s
2025-09-06 03:35:06 -05:00
fdc1c4b6cb Restart nginx container after renewing certificates
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-03 00:09:44 -05:00
1063a538f2 Run certificate check weekly
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-03 00:08:47 -05:00
0e056afbf7 Add workflow to setup/renew certificates
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-03 00:06:36 -05:00
675be10668 Split steps, to make process clearer
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-02 23:48:30 -05:00
dbca094ba5 Switch back, since key is no longer password protected
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-02 23:47:19 -05:00
cba814c2e3 Pull code into the correct directory
All checks were successful
Deploy homelab / Deploy (push) Successful in 3s
2025-09-02 23:37:37 -05:00
739037b787 Pull latest changes from main before redeploying 2025-09-02 23:34:48 -05:00
3b29cf8ab4 Silence warnings by adding TZ env var
All checks were successful
Deploy homelab / Deploy (push) Successful in 11s
2025-09-02 23:31:56 -05:00
df87c0b983 Add CD to deploy containers
All checks were successful
Deploy homelab / Deploy (push) Successful in 2s
2025-09-02 23:29:18 -05:00
f74d197e8d Ensure only one job runs on the host runner at a time 2025-09-02 23:24:13 -05:00
e8228968a3 Update runners 2025-09-02 23:23:21 -05:00
3641a304b6 Changes to fix gitea package repo 2025-09-02 22:40:15 -05:00
18 changed files with 781 additions and 65 deletions

View File

@@ -0,0 +1,28 @@
name: "Build certificates"
on:
workflow_dispatch:
inputs:
# Note: this doesn't work on current gitea for some reason?
build_certs:
description: "Build certificates from scratch"
type: "boolean"
required: true
default: false
schedule: "@weekly"
env:
TZ: "America/Chicago"
jobs:
deploy:
name: "Setup/Renew certificates"
runs-on: "homelab"
steps:
- name: "Build certificates"
if: inputs.build_certs
run: |
cd /home/matthew/homelab
bash ./build-certs.sh
- name: "Renew certificates"
run: |
cd /home/matthew/homelab
docker compose run --rm certbot renew
docker restart homelab-web-1

View File

@@ -0,0 +1,21 @@
name: Deploy homelab
on:
push:
branches: main
env:
TZ: America/Chicago
jobs:
deploy:
name: Deploy
runs-on: homelab
steps:
- name: "Pull latest code"
run: |
cd /home/matthew/homelab
git checkout main
git pull
- name: "Deploy containers"
run: |
cd /home/matthew/homelab
docker compose up -d --remove-orphans

45
README.md Normal file
View File

@@ -0,0 +1,45 @@
# My personal homelab setup
Currently running on a Debian host
## Raw data
Raw data is stored in `/data`, a ZFS data set
```bash
# Install ZFS
apt update
apt install linux-headers-amd64
apt install zfsutils-linux zfs-dkms
zpool create hdd raidz2 <disks...>
mkdir -p /data
zfs create -o mountpoint=/data hdd/data
zfs set compression=on hdd/data
```
## act_runner
```bash
pushd /tmp
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-linux-amd64.xz
xz -d act_runner-0.2.13-linux-amd64.xz
mv act_runner-0.2.13-linux-amd64 /usr/bin/act_runner
chmod +x /usr/bin/act_runner
mkdir /home/matthew/act_runner
```
## Systemd
```bash
# Add services
ln -s $PWD/*.service /etc/systemd/system/
systemctl enable homelab
systemctl start homelab
cd ~/act_runner
/usr/bin/act_runner register --config /home/matthew/homelab/host-runner.yaml
systemctl enable act_runner
systemctl start act_runner
```

16
act_runner.service Normal file
View File

@@ -0,0 +1,16 @@
[Unit]
Description=Gitea Actions runner
Documentation=https://gitea.com/gitea/act_runner
After=docker.service
[Service]
ExecStart=/usr/bin/act_runner daemon --config /home/matthew/homelab/host-runner.yaml
ExecReload=/bin/kill -s HUP $MAINPID
WorkingDirectory=/home/matthew/act_runner
TimeoutSec=0
RestartSec=10
Restart=always
User=matthew
[Install]
WantedBy=multi-user.target

View File

@@ -6,7 +6,7 @@ authentication_backend:
password_change:
disable: false
file:
path: '/config/users.yml'
path: '/data/users.yml'
watch: false
search:
email: false
@@ -37,18 +37,72 @@ session:
remember_me: '1d'
notifier:
disable_startup_check: false
filesystem:
filename: '/config/notification.txt'
# filesystem:
# filename: '/data/notification.txt'
smtp:
address: 'smtp://mail:25'
sender: 'Authelia <auth@loadingm.xyz>'
disable_require_tls: true # Determine if this is needed
disable_starttls: true
storage:
local:
path: '/config/db.sqlite3'
path: '/data/db.sqlite3'
access_control:
default_policy: deny
rules:
- domain: '*.loadingm.xyz'
- domain: 'servarr.loadingm.xyz'
subject:
- 'group:admins'
policy: one_factor
# - domain: '*.loadingm.xyz'
# policy: one_factor
server:
endpoints:
authz:
auth-request:
implementation: 'AuthRequest'
identity_providers:
oidc:
# enable_client_debug_messages: false
# minimum_parameter_entropy: 8
# enforce_pkce: 'public_clients_only'
# enable_pkce_plain_challenge: false
# enable_jwt_access_token_stateless_introspection: false
# discovery_signed_response_alg: 'none'
# discovery_signed_response_key_id: ''
# require_pushed_authorization_requests: false
# authorization_policies:
# policy_name:
# default_policy: 'two_factor'
# rules:
# - policy: 'deny'
# subject: 'group:services'
# networks:
# - '192.168.1.0/24'
# - '192.168.2.51'
lifespans:
access_token: '1h'
authorize_code: '1m'
id_token: '1h'
refresh_token: '90m'
# claims_policies:
# policy_name:
# id_token: []
# access_token: []
# id_token_audience_mode: 'specification'
# custom_claims:
# claim_name:
# name: 'claim_name'
# attribute: 'attribute_name'
# scopes:
# scope_name:
# claims: []
# cors:
# endpoints:
# - 'authorization'
# - 'token'
# - 'revocation'
# - 'introspection'
# allowed_origins:
# - 'https://example.com'
# allowed_origins_from_client_redirect_uris: false

View File

@@ -0,0 +1,31 @@
# rand() {
# docker run --rm authelia/authelia:latest authelia crypto rand --length $1 --charset rfc3986
# }
# hash() {
# docker run --rm authelia/authelia:latest authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length $1 --random.charset rfc3986
# }
identity_providers:
oidc:
## The other portions of the mandatory OpenID Connect 1.0 configuration go here.
## See: https://www.authelia.com/c/oidc
clients:
- client_name: 'Gitea'
client_id: '$(rand 72)'
client_secret: '$(hash 72)'
public: false
authorization_policy: 'two_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://gitea.loadingm.xyz/user/oauth2/authelia/callback'
scopes:
- 'openid'
- 'email'
- 'profile'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic'

View File

@@ -1,5 +1,5 @@
docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ \
docker compose run --rm certbot certonly -v --webroot --webroot-path /var/www/certbot/ \
-d loadingm.xyz \
-d gitea.loadingm.xyz \
-d auth.loadingm.xyz \
@@ -7,4 +7,6 @@ docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certb
-d jellyseerr.loadingm.xyz \
-d servarr.loadingm.xyz \
-d karakeep.loadingm.xyz \
-d ollama.loadingm.xyz
-d ollama.loadingm.xyz \
-d memos.loadingm.xyz \
-d gpodder.loadingm.xyz

View File

@@ -1,6 +1,41 @@
include:
- ./karakeep-compose.yaml
- ./jellyfin-compose.yaml
secrets:
JWT_SECRET:
file: '/data/authelia/secrets/JWT_SECRET'
SESSION_SECRET:
file: '/data/authelia/secrets/SESSION_SECRET'
STORAGE_PASSWORD:
file: '/data/authelia/secrets/STORAGE_PASSWORD'
STORAGE_ENCRYPTION_KEY:
file: '/data/authelia/secrets/STORAGE_ENCRYPTION_KEY'
volumes:
meilisearch:
karakeep:
networks:
karakeep:
external: false
karakeep-int:
external: false
ollama:
external: false
ollama-int:
external: false
jellyfin:
external: false
jellyfin-int:
external: false
auth:
external: false
gitea:
external: false
gpodder:
external: false
memos:
external: false
mail:
external: false
services:
web:
image: "nginx"
@@ -20,12 +55,21 @@ services:
- jellyfin
- jellyfin-int
- auth
- gitea
- gpodder
- memos
depends_on:
- jellyfin
- ollama-webui
- karakeep-web
- authelia
- qbittorrent
- gitea
- gpodder
- memos
logging: &logging
options:
max-size: "50m"
# Optional - extra fonts to be used during transcoding with subtitle burn-in
# - type: bind
# source: /usr/local/share/fonts/cu
@@ -37,20 +81,24 @@ services:
- /data/certbot/www/:/var/www/certbot/:rw
- /data/certbot/conf/:/etc/letsencrypt/:rw
authelia:
container_name: 'authelia'
image: 'docker.io/authelia/authelia:latest'
command:
- 'authelia'
- '--config=/config/configuration.yml'
- '--config=/data/configuration.yml'
restart: 'unless-stopped'
secrets: ['JWT_SECRET', 'SESSION_SECRET', 'STORAGE_PASSWORD', 'STORAGE_ENCRYPTION_KEY']
networks:
- auth
- mail
environment:
AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: '/run/secrets/JWT_SECRET'
AUTHELIA_SESSION_SECRET_FILE: '/run/secrets/SESSION_SECRET'
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: '/run/secrets/STORAGE_ENCRYPTION_KEY'
volumes:
- './authelia/:/config'
# webdav:
# image: ""
- './authelia/:/config:ro'
- '/data/authelia/:/data'
logging: *logging
minecraft:
image: itzg/minecraft-server:latest
tty: true
@@ -73,54 +121,97 @@ services:
187eca31-2e33-4199-97e0-2286bf35f7f8
PAUSE_WHEN_EMPTY_SECONDS: "20"
ENABLE_ROLLING_LOGS: "true"
REMOVE_OLD_MODS: "TRUE"
logging: *logging
volumes:
- "/opt/minecraft:/data"
- "/data/minecraft/data:/data"
- "/data/mincraft/mods:/mods"
- "/data/mincraft/plugins:/plugins"
- "/data/mincraft/config:/config"
gitea:
image: gitea/gitea:latest
image: docker.gitea.com/gitea:1.24
environment:
- USER_UID=1000
- USER_GID=1000
- USER_UID=106
- USER_GID=110
- ENABLE_NOTIFY_MAIL=true
# -
restart: unless-stopped
networks:
- gitea
- mail
volumes:
- /data/gitea/data:/data
- /home/git/.ssh/:/data/git/.ssh
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "222:22"
logging: *logging
depends_on:
- authelia
gitea-runner:
image: docker.gitea.com/act_runner:latest
restart: unless-stopped
networks:
- gitea
environment:
- CONFIG_FILE=/config.yaml
- GITEA_INSTANCE_URL=https://gitea.loadingm.xyz/
- GITEA_RUNNER_REGISTRATION_TOKEN=i04H1aJxHByflAjVneA0G5CmPl1ntQDtGDeZCBnM
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /data/gitea/runner/:/data
- ./gitea-runner.yaml:/config.yaml
logging: *logging
depends_on:
- gitea
gpodder:
image: gitea.loadingm.xyz/the10thwiz/gpodder-rs:latest
restart: unless-stopped
environment:
- ROCKET_SECRET_KEY=${GPODDER_SECRET_KEY}
networks:
- gpodder
volumes:
- /data/gpodder:/data
logging: *logging
tftp:
image: kaczmar2/tftp-server
restart: unless-stopped
environment:
- ENABLE_WEB_SERVER=false
network_mode: host
volumes:
- /data/tftp:/srv/tftp:ro
- /etc/localtime:/etc/localtime:ro
logging: *logging
memos:
image: neosmemo/memos:stable
networks:
- memos
volumes:
- /data/memos:/var/opt/memos
environment:
- MEMOS_MODE=prod
- MEMOS_PORT=5230
restart: unless-stopped
logging: *logging
mail:
image: boky/postfix
restart: unless-stopped
logging: *logging
environment:
- ALLOWED_SENDER_DOMAINS=loadingm.xyz
- POSTFIX_myhostname=mail
volumes:
- /data/mail:/etc/opendkim/keys
networks:
- mail
ports:
- 127.0.0.1:25:25
# calibre:
# image: "linuxserver/calibre-web"
# 5d-diplomacy-frontend:
# image: ""
# 5d-diplomacy-backend:
# image: ""
secrets:
JWT_SECRET:
file: './authelia/secrets/JWT_SECRET'
SESSION_SECRET:
file: './authelia/secrets/SESSION_SECRET'
STORAGE_PASSWORD:
file: './authelia/secrets/STORAGE_PASSWORD'
STORAGE_ENCRYPTION_KEY:
file: './authelia/secrets/STORAGE_ENCRYPTION_KEY'
volumes:
meilisearch:
karakeep:
networks:
karakeep:
external: false
karakeep-int:
external: false
ollama:
external: false
ollama-int:
external: false
jellyfin:
external: false
jellyfin-int:
external: false
auth:
external: false
gitea:
external: false

113
gitea-runner.yaml Normal file
View File

@@ -0,0 +1,113 @@
# Example configuration file, it's safe to copy this as the default config file without any modification.
# You don't have to copy this file to your instance,
# just run `./act_runner generate-config > config.yaml` to generate a config file.
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info
runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 20
# Extra environment variables to run jobs.
envs:
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .env
# The timeout for a job to be finished.
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
# So the job could be stopped by the Gitea instance if it's timeout is shorter than this.
timeout: 3h
# The timeout for the runner to wait for running jobs to finish when shutting down.
# Any running jobs that haven't finished after this timeout will be cancelled.
shutdown_timeout: 0s
# Whether skip verifying the TLS certificate of the Gitea instance.
insecure: false
# The timeout for fetching the job from the Gitea instance.
fetch_timeout: 5s
# The interval for fetching the job from the Gitea instance.
fetch_interval: 2s
# The github_mirror of a runner is used to specify the mirror address of the github that pulls the action repository.
# It works when something like `uses: actions/checkout@v4` is used and DEFAULT_ACTIONS_URL is set to github,
# and github_mirror is not empty. In this case,
# it replaces https://github.com with the value here, which is useful for some special network environments.
github_mirror: ''
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
# Like: "macos-arm64:host" or "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
# Find more images provided by Gitea at https://gitea.com/docker.gitea.com/runner-images .
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when execute `daemon`, will use labels in `.runner` file.
labels:
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
- "ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04"
- "rustup-all:docker://gitea.loadingm.xyz/the10thwiz/rustup:latest"
- "rustup-all-musl:docker://gitea.loadingm.xyz/the10thwiz/rustup:musl-latest"
- "rustup-stable:docker://gitea.loadingm.xyz/the10thwiz/rustup:stable"
- "rustup-beta:docker://gitea.loadingm.xyz/the10thwiz/rustup:beta"
- "rustup-nightly:docker://gitea.loadingm.xyz/the10thwiz/rustup:nightly"
cache:
# Enable cache server to use actions/cache.
enabled: true
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: ""
# The port of the cache server.
# 0 means to use a random available port.
port: 0
# The external cache server URL. Valid only when enable is true.
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
# The URL should generally end with "/".
external_server: ""
container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, act_runner will create a network automatically.
network: ""
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
options:
# The parent directory of a job's working directory.
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
# If the path starts with '/', the '/' will be trimmed.
# For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: []
# overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: ""
# Pull docker image(s) even if already present
force_pull: false
# Rebuild docker image(s) even if already present
force_rebuild: false
# Always require a reachable docker daemon, even if not required by act_runner
require_docker: false
# Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or act_runner
docker_timeout: 0s
host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:

20
homelab.service Normal file
View File

@@ -0,0 +1,20 @@
[Unit]
Description=Homelab services
Requires=docker.service
After=docker.service
[Service]
Restart=always
User=root
Group=docker
TimeoutStopSec=15
WorkingDirectory=/home/matthew/homelab
# Shutdown container (if running) when unit is started
ExecStartPre=/usr/bin/docker compose -f docker-compose.yaml down
# Start container when unit is started
ExecStart=/usr/bin/docker compose -f docker-compose.yaml up
# Stop container when unit is stopped
ExecStop=/usr/bin/docker compose -f docker-compose.yaml down
[Install]
WantedBy=multi-user.target

106
host-runner.yaml Normal file
View File

@@ -0,0 +1,106 @@
# Example configuration file, it's safe to copy this as the default config file without any modification.
# You don't have to copy this file to your instance,
# just run `./act_runner generate-config > config.yaml` to generate a config file.
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info
runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 1
# Extra environment variables to run jobs.
envs:
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .env
# The timeout for a job to be finished.
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
# So the job could be stopped by the Gitea instance if it's timeout is shorter than this.
timeout: 3h
# The timeout for the runner to wait for running jobs to finish when shutting down.
# Any running jobs that haven't finished after this timeout will be cancelled.
shutdown_timeout: 0s
# Whether skip verifying the TLS certificate of the Gitea instance.
insecure: false
# The timeout for fetching the job from the Gitea instance.
fetch_timeout: 5s
# The interval for fetching the job from the Gitea instance.
fetch_interval: 2s
# The github_mirror of a runner is used to specify the mirror address of the github that pulls the action repository.
# It works when something like `uses: actions/checkout@v4` is used and DEFAULT_ACTIONS_URL is set to github,
# and github_mirror is not empty. In this case,
# it replaces https://github.com with the value here, which is useful for some special network environments.
github_mirror: ''
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
# Like: "macos-arm64:host" or "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
# Find more images provided by Gitea at https://gitea.com/docker.gitea.com/runner-images .
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when execute `daemon`, will use labels in `.runner` file.
labels:
- "homelab:host"
cache:
# Enable cache server to use actions/cache.
enabled: true
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: ""
# The port of the cache server.
# 0 means to use a random available port.
port: 0
# The external cache server URL. Valid only when enable is true.
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
# The URL should generally end with "/".
external_server: ""
container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, act_runner will create a network automatically.
network: ""
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
options:
# The parent directory of a job's working directory.
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
# If the path starts with '/', the '/' will be trimmed.
# For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: []
# overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: ""
# Pull docker image(s) even if already present
force_pull: false
# Rebuild docker image(s) even if already present
force_rebuild: false
# Always require a reachable docker daemon, even if not required by act_runner
require_docker: false
# Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or act_runner
docker_timeout: 0s
host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:

View File

@@ -1,7 +1,37 @@
services:
gluetun:
image: qmcgaw/gluetun
cap_add:
- NET_ADMIN
ports:
- 8080:8080
- 51820:51820
- 51820:51820/udp
- 46931:46931
- 46931:46931/udp
networks:
- jellyfin-int
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- VPN_ENDPOINT_IP=${ENDPOINT_IP}
- VPN_ENDPOINT_PORT=${ENDPOINT_PORT}
- WIREGUARD_ADDRESSES=${WIREGUARD_ADDR}
- VPN_DNS_ADDRESS=${DNS_ADDRESS}
- WIREGUARD_PUBLIC_KEY=${PUBLIC_KEY}
- WIREGUARD_PRIVATE_KEY=${PRIVATE_KEY}
- VPN_PORT_FORWARDING=on
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
- VPN_PORT_FORWARDING_STATUS_FILE=/tmp/gluetun/forwarded_port
- TZ=${TZ}
- UPDATER_PERIOD=24h
restart: always
volumes:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/gluetun:/tmp/gluetun
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
network_mode: service:gluetun
environment:
- WEBUI_PORT=8080
- PUID=0
@@ -11,17 +41,18 @@ services:
volumes:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/configs/qbittorrent:/config
- /data/jellyfin/qbittorrent/downloads:/downloads
ports:
- 8080:8080
- 6881:6881
- 6881:6881/udp
networks:
- jellyfin-int
# - /data/jellyfin/qbittorrent/downloads:/data/jellyfin/qbittorrent/downloads
# ports:
# - 8080:8080
# - 6881:6881
# - 6881:6881/udp
# networks:
# - jellyfin-int
depends_on:
- gluetun
restart: unless-stopped
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
environment:
- LOG_LEVEL=${LOG_LEVEL:-info}
- LOG_HTML=${LOG_HTML:-false}
@@ -36,7 +67,6 @@ services:
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=0
- PGID=0
@@ -50,7 +80,6 @@ services:
restart: unless-stopped
jackett:
image: lscr.io/linuxserver/jackett:latest
container_name: jackett
environment:
- PUID=0
- PGID=0
@@ -64,7 +93,6 @@ services:
restart: unless-stopped
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=0
- PGID=0
@@ -81,7 +109,6 @@ services:
restart: unless-stopped
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=0
- PGID=0
@@ -98,7 +125,6 @@ services:
restart: unless-stopped
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=0
- PGID=0
@@ -121,9 +147,20 @@ services:
- /data/jellyfin/radarr/movies:/data/movies
- /data/jellyfin/qbittorrent/downloads:/data/media_downloads
restart: unless-stopped
group_add:
- '993'
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
# runtime: nvidia
# deploy:
# resources:
# reservations:
# devices:
# - driver: intel
# count: all
# capabilities: [gpu]
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
environment:
- LOG_LEVEL=debug
- TZ=${TZ}

View File

@@ -52,11 +52,10 @@ services:
networks:
- karakeep-int
ollama:
image: docker.io/ollama/ollama:latest
image: docker.io/ollama/ollama:0.11.10
volumes:
- .:/code
- /data/library/ollama/ollama:/root/.ollama
container_name: ollama
pull_policy: always
tty: true
restart: always
@@ -69,7 +68,6 @@ services:
ollama-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: ollama-webui
volumes:
- /data/library/ollama/ollama-webui:/app/backend/data
depends_on:

View File

@@ -22,7 +22,7 @@ server {
server_name gitea.loadingm.xyz;
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 200M;
client_max_body_size 200G;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;

View File

@@ -0,0 +1,80 @@
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
server {
listen 80;
listen [::]:80;
server_name gpodder.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# Default server configuration
#
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name gpodder.loadingm.xyz;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
# Permissions policy. May cause issues with some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main karakeep traffic
proxy_pass http://gpodder:8000;
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-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -40,7 +40,17 @@ server {
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
set $CSP "default-src https: data: blob:";
set $CSP "$CSP; img-src 'self' https://* data:";
set $CSP "$CSP; style-src 'self' 'unsafe-inline' data:";
set $CSP "$CSP; style-src-elem 'self' 'unsafe-inline' data:";
set $CSP "$CSP; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtubse.com blob: data:";
set $CSP "$CSP; worker-src 'self' blob: data:";
set $CSP "$CSP; connect-src 'self' data:";
set $CSP "$CSP; object-src 'none' data:";
set $CSP "$CSP; frame-ancestors 'self' data:";
set $CSP "$CSP; font-src 'self' data:";
add_header Content-Security-Policy $CSP;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
@@ -55,6 +65,7 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_hide_header Content-Security-Policy;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;

62
nginx/sites-enabled/memos Normal file
View File

@@ -0,0 +1,62 @@
server {
listen 80;
listen [::]:80;
server_name memos.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name memos.loadingm.xyz;
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 200G;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
# Permissions policy. May cause issues with some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main karakeep traffic
proxy_pass http://memos:5230;
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-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -13,7 +13,8 @@ server {
location /qbt/ {
# include /etc/nginx/snippets/proxy.conf;
include /etc/nginx/snippets/authelia-authrequest.conf;
proxy_pass http://qbittorrent:8080/;
# proxy_pass http://qbittorrent:8080/;
proxy_pass http://gluetun:8080/;
proxy_http_version 1.1;
proxy_set_header Host $proxy_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;