feat: add Traefik, Uptime Kuma, Transmission, Jellyfin, Gitea, Home Assistant, and a simple homepage

This commit is contained in:
Anton Shubin 2024-01-21 00:22:19 +08:00
commit b290df1304
12 changed files with 610 additions and 0 deletions

12
.env.example Normal file
View File

@ -0,0 +1,12 @@
CONTACT_EMAIL=your@email.com
SSH_TO_SERVER=user@server
PATH_APPS=~/apps
PATH_MOVIES=~/movies
HOSTNAME_UPTIME_KUMA=uptime.example.com
HOSTNAME_TORRENTS=torrents.example.com
HOSTNAME_MOVIES=movies.example.com
HOSTNAME_GITEA=git.example.com
HOSTNAME_HOME_ASSISTANT=smart.example.com
HOSTNAME_HOMEPAGE=ui.example.com
HOSTNAME_SAGE=sage.example.com
HOSTNAME_AQS=example.com

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.volumes
.env
dist

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

12
.idea/homelab.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/homelab.iml" filepath="$PROJECT_DIR$/.idea/homelab.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

12
Makefile Normal file
View File

@ -0,0 +1,12 @@
-include .env
export $(shell sed 's/=.*//' .env)
# Replace env variables in index.html
build-homepage:
mkdir -p ./homepage/dist
envsubst < ./homepage/src/index.html > ./homepage/dist/index.html
deploy:
make build-homepage
rsync -avz -e 'ssh' --include-from='deploy.files.txt' --exclude '*' ./ $(SSH_TO_SERVER):$(PATH_APPS)
ssh homelab "cd $(PATH_APPS) && docker compose up -d"

50
README.md Normal file
View File

@ -0,0 +1,50 @@
# Homelab server
This is a collection of services I run on my homelab server.
It's pretty lightweight (you need at least 2GB RAM) and easy to setup.
All you need is a linux server with [Docker](https://get.docker.com/) installed.
Make sure you followed instructions after installation to configure to run Docker as a non-root user.
## Services
### [Traefik](https://github.com/traefik/traefik)
A reverse proxy that is used to route incoming requests to the correct container by domain name and not by port.
It's configured to use Let's Encrypt to automatically generate SSL certificates and redirect all HTTP requests to HTTPS.
Ex: https://movies.example.com -> jellyfin container:8096
Ex: https://gitea.example.com -> gitea container:3000
### [Uptime Kuma](https://github.com/louislam/uptime-kuma)
Uptime Kuma is a monitoring tool, that checks the status of your websites and APIs.
### [Transmission](https://github.com/transmission/transmission)
Transmission is a BitTorrent client with a web interface.
It is a lightweight, works on the server in background and has zero configuration.
### [Jellyfin](https://github.com/jellyfin/jellyfin)
Jellyfin is a media server for hosting and managing personal media libraries.
Think of movies, TV shows, home videos, music, and pictures.
### [Gitea](https://github.com/go-gitea/gitea)
Gitea is a lightweight self-hosted Git service, similar to GitHub.
### [Home Assistant](https://github.com/home-assistant/home-assistant.io)
Home Assistant is an open-source home automation platform.
For your smart home, it is the software "hub" that allows you to control all your devices.
### [Homepage](./homepage/src/index.html)
A simple homepage with links to all the services.
## Setup
To start you need to create .env file by copying .env.example:
```bash
cp .env.example .env
```
and filling in the variables.
Then you can deploy the stack to your server:
```bash
make deploy
```
That's it! You can now access the services by going to the domain names you specified in the .env file.
If you want to add more services, just add them to the `compose.yml` file and run `make deploy` again.

228
compose.yml Normal file
View File

@ -0,0 +1,228 @@
version: '3.8'
services:
# Traefik is a reverse proxy and load balancer.
# It is used to route incoming requests to the correct container by domain name and not by port.
# Ex: https://movies.example.com -> jellyfin container:8096
# Ex: https://gitea.example.com -> gitea container:3000
# It's configured to use Let's Encrypt to automatically generate SSL certificates and redirect all HTTP requests to HTTPS.
traefik:
container_name: "traefik"
image: "traefik"
restart: unless-stopped
command:
# - "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
# - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=${CONTACT_EMAIL}"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
# - "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# Uptime Kuma is a monitoring tool, that checks the status of your websites and APIs.
uptime-kuma:
container_name: uptime-kuma
image: louislam/uptime-kuma
volumes:
- ./.volumes/uptime-kuma:/app/data
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_UPTIME_KUMA}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 256M
cpus: '0.25'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.uptime-kuma.rule=Host(`${HOSTNAME_UPTIME_KUMA}`)"
- "traefik.http.routers.uptime-kuma.entrypoints=websecure"
- "traefik.http.routers.uptime-kuma.tls=true"
- "traefik.http.routers.uptime-kuma.tls.certresolver=myresolver"
- "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001"
# Transmission is a BitTorrent client with a web interface.
# It is a lightweight, works on the server in background and has zero configuration.
transmission:
image: linuxserver/transmission
container_name: transmission
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Singapore
volumes:
- ./.volumes/transmission:/config
- ${PATH_MOVIES}:/downloads
ports:
- 51413:51413 # Default port for torrent traffic
- 51413:51413/udp # Default port for DHT
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_TORRENTS}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 256M
cpus: '0.25'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.transmission.rule=Host(`${HOSTNAME_TORRENTS}`)"
- "traefik.http.routers.transmission.entrypoints=websecure"
- "traefik.http.routers.transmission.tls=true"
- "traefik.http.routers.transmission.tls.certresolver=myresolver"
- "traefik.http.services.transmission.loadbalancer.server.port=9091"
# Jellyfin is a media server for hosting and managing personal media libraries.
# Think of movies, TV shows, home videos, music, and pictures.
jellyfin:
container_name: jellyfin
image: jellyfin/jellyfin
volumes:
- ./.volumes/jellyfin:/config
- ./.volumes/jellyfin/cache:/cache
- ${PATH_MOVIES}:/media
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_MOVIES}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 2048M
cpus: '2'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.jellyfin.rule=Host(`${HOSTNAME_MOVIES}`)"
- "traefik.http.routers.jellyfin.entrypoints=websecure"
- "traefik.http.routers.jellyfin.tls=true"
- "traefik.http.routers.jellyfin.tls.certresolver=myresolver"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
# Gitea is a lightweight self-hosted Git service.
gitea:
container_name: gitea
image: gitea/gitea:latest
ports:
- 222:22
volumes:
- ./.volumes/gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- USER_UID=1000
- USER_GID=1000
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_GITEA}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 256M
cpus: '0.25'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitea.rule=Host(`${HOSTNAME_GITEA}`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls=true"
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
# Home Assistant is an open-source home automation platform.
# For your smart home, it is the software "hub" that allows you to control all your devices.
home-assistant:
container_name: home-assistant
image: homeassistant/home-assistant:stable
volumes:
- ./.volumes/home-assistant:/config
environment:
- TZ=Asia/Singapore
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_HOME_ASSISTANT}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 512M
cpus: '0.25'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.home-assistant.rule=Host(`${HOSTNAME_HOME_ASSISTANT}`)"
- "traefik.http.routers.home-assistant.entrypoints=websecure"
- "traefik.http.routers.home-assistant.tls=true"
- "traefik.http.routers.home-assistant.tls.certresolver=myresolver"
- "traefik.http.services.home-assistant.loadbalancer.server.port=8123"
# A simple HTML page to display links to all the services.
homepage:
container_name: homepage
image: nginx:alpine
volumes:
- ./homepage/dist:/usr/share/nginx/html:ro
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "${HOSTNAME_HOMEPAGE}" ]
interval: 1m
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
memory: 128M
cpus: '0.10'
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.homepage.rule=Host(`${HOSTNAME_HOMEPAGE}`)"
- "traefik.http.routers.homepage.entrypoints=websecure"
- "traefik.http.routers.homepage.tls=true"
- "traefik.http.routers.homepage.tls.certresolver=myresolver"
- "traefik.http.services.homepage.loadbalancer.server.port=80"

158
configs/smb.conf Executable file
View File

@ -0,0 +1,158 @@
# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options (perhaps too
# many!) most of which are not shown in this example
#
# For a step to step guide on installing, configuring and using samba,
# read the Samba-HOWTO-Collection. This may be obtained from:
# http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf
#
# Many working examples of smb.conf files can be found in the
# Samba-Guide which is generated daily and can be downloaded from:
# http://www.samba.org/samba/docs/Samba-Guide.pdf
#
# Any line which starts with a ; (semi-colon) or a # (hash)
# is a comment and is ignored. In this example we will use a #
# for commentry and a ; for parts of the config file that you
# may wish to enable
#
# NOTE: Whenever you modify this file you should run the command "testparm"
# to check that you have not made any basic syntactic errors.
#
#======================= Global Settings =====================================
[global]
# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
workgroup = WORKGROUP
# server string is the equivalent of the NT Description field
server string = Samba Server
# Server role. Defines in which mode Samba will operate. Possible
# values are "standalone server", "member server", "classic primary
# domain controller", "classic backup domain controller", "active
# directory domain controller".
#
# Most people will want "standalone server" or "member server".
# Running as "active directory domain controller" will require first
# running "samba-tool domain provision" to wipe databases and create a
# new domain.
server role = standalone server
# This option is important for security. It allows you to restrict
# connections to machines which are on your local network. The
# following example restricts access to two C class networks and
# the "loopback" interface. For more examples of the syntax see
# the smb.conf man page
; hosts allow = 192.168.1. 192.168.2. 127.
# Uncomment this if you want a guest account, you must add this to /etc/passwd
# otherwise the user "nobody" is used
; guest account = pcguest
# this tells Samba to use a separate log file for each machine
# that connects
log file = /dev/stdout
# Put a capping on the size of the log files (in Kb).
max log size = 50
# Specifies the Kerberos or Active Directory realm the host is part of
; realm = MY_REALM
# Backend to store user information in. New installations should
# use either tdbsam or ldapsam. smbpasswd is available for backwards
# compatibility. tdbsam requires no further configuration.
; passdb backend = tdbsam
# Using the following line enables you to customise your configuration
# on a per machine basis. The %m gets replaced with the netbios name
# of the machine that is connecting.
# Note: Consider carefully the location in the configuration file of
# this line. The included file is read at that point.
; include = /usr/local/samba/lib/smb.conf.%m
# Configure Samba to use multiple interfaces
# If you have multiple network interfaces then you must list them
# here. See the man page for details.
; interfaces = 192.168.12.2/24 192.168.13.2/24
# Where to store roving profiles (only for Win95 and WinNT)
# %L substitutes for this servers netbios name, %U is username
# You must uncomment the [Profiles] share below
; logon path = \\%L\Profiles\%U
# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
; wins support = yes
# WINS Server - Tells the NMBD components of Samba to be a WINS Client
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
; wins server = w.x.y.z
# WINS Proxy - Tells Samba to answer name resolution queries on
# behalf of a non WINS capable client, for this to work there must be
# at least one WINS Server on the network. The default is NO.
; wins proxy = yes
# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
# via DNS nslookups. The default is NO.
dns proxy = no
# These scripts are used on a domain controller or stand-alone
# machine to add or delete corresponding unix accounts
; add user script = /usr/sbin/useradd %u
; add group script = /usr/sbin/groupadd %g
; add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u
; delete user script = /usr/sbin/userdel %u
; delete user from group script = /usr/sbin/deluser %u %g
; delete group script = /usr/sbin/groupdel %g
pam password change = yes
map to guest = bad user
usershare allow guests = yes
create mask = 0664
force create mode = 0664
directory mask = 0775
force directory mode = 0775
force user = smbuser
force group = smb
follow symlinks = yes
load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes
strict locking = no
aio read size = 0
aio write size = 0
vfs objects = catia fruit streams_xattr
# Security
client ipc max protocol = SMB3
client ipc min protocol = SMB2_10
client max protocol = SMB3
client min protocol = SMB2_10
server max protocol = SMB3
server min protocol = SMB2_10
# Time Machine
fruit:delete_empty_adfiles = yes
fruit:time machine = yes
fruit:veto_appledouble = no
fruit:wipe_intentionally_left_blank_rfork = yes
# macOS support for write
fruit:metadata = stream
fruit:model = MacSamba
fruit:posix_rename = yes
fruit:nfs_aces = no
[media]
path = /home/pi/media
browsable = yes
read only = no
guest ok = no
veto files = /.apdisk/.DS_Store/.TemporaryItems/.Trashes/desktop.ini/ehthumbs.db/Network Trash Folder/Temporary Items/Thumbs.db/
delete veto files = yes

3
deploy.files.txt Normal file
View File

@ -0,0 +1,3 @@
compose.yml
homepage/dist/***
.env

110
homepage/src/index.html Normal file
View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: Arial, sans-serif;
background-color: #121212;
color: #ffffff;
margin: 0;
padding: 20px;
}
h1 {
text-align: center;
}
.container {
max-width: 300px;
margin: 0 auto;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
text-align: center;
}
a {
display: block;
padding: 15px 20px;
text-decoration: none;
color: white;
background-color: #1e1e1e;
border-radius: 5px;
font-size: 30px;
transition: background-color 0.3s ease;
}
a:hover, a:focus {
background-color: #2979ff;
}
</style>
<title>Home</title>
</head>
<body>
<h1>Homelab</h1>
<div class="container">
<ul>
<li>
<a href="https://$HOSTNAME_SAGE"
target="_blank">
🧠 Sage
</a>
</li>
<li>
<a href="https://$HOSTNAME_AQS"
target="_blank">
🌬️ Air Quality Sensor
</a>
</li>
<li>
<a href="https://$HOSTNAME_UPTIME_KUMA/status/tod"
target="_blank">
⏱️ Uptime (TOD)
</a>
</li>
<li>
<a href="https://$HOSTNAME_UPTIME_KUMA"
target="_blank">
⏱️ Uptime Kuma
</a>
</li>
<li>
<a href="https://$HOSTNAME_TORRENTS"
target="_blank">
⬇️ Torrents
</a>
</li>
<li>
<a href="https://$HOSTNAME_MOVIES"
target="_blank">
🎬 Movies
</a>
</li>
<li>
<a href="https://$HOSTNAME_GITEA"
target="_blank">
📦 Gitea
</a>
</li>
<li>
<a href="https://$HOSTNAME_HOME_ASSISTANT"
target="_blank">
⚡ Home Assistant
</a>
</li>
</ul>
</div>
</body>
</html>