In this article, we will be exploring the following services
I use these two on a daily basis. You can explore other self-hosted services in https://selfh.st/
Since we have already discussed reverse proxy, setting up VPN and other topics, this blog will be quite easy to pick up because we are just adding new services.
Immich
Immich is an image backup service. It looks almost like a clone of Google Photos, and I feel like it's too good to be true. You basically host your own Google Photos, download a mobile app available on both Android and iOS, and now your personal computer is the cloud. You can easily back up all your photos to your computer while also being able to share these photos, create albums, group by faces, and much more.
To set up Immich, it's as easy as it gets. But first, let's create a docker network so the nginx and immich can remain in the same docker network
docker network create homelab_network
Now we use this network in both the nginx and immich.
Nginx docker-compose.yml
version: '2.2'
services:
nginxproxymanager:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginxproxymanager
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./nginx/data:/data
- ./nginx/letsencrypt:/etc/letsencrypt
networks:
default:
name: homelab_network
external: True
Immich docker-compose.yml
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- 2283:3001
depends_on:
- redis
- database
restart: always
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
redis:
container_name: immich_redis
image: docker.io/redis:6.2-alpine@sha256:d6c2911ac51b289db208767581a5d154544f2b2fe4914ea5056443f62dc6e900
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
healthcheck:
test: pg_isready --dbname='${DB_DATABASE_NAME}' || exit 1; Chksum="$$(psql --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
interval: 5m
start_interval: 30s
start_period: 5m
command: ["postgres", "-c" ,"shared_preload_libraries=vectors.so", "-c", 'search_path="$$user", public, vectors', "-c", "logging_collector=on", "-c", "max_wal_size=2GB", "-c", "shared_buffers=512MB", "-c", "wal_compression=on"]
restart: always
volumes:
model-cache:
networks:
default:
name: homelab_network
external: True
For immich to run, we need to create a .env file to set the following variables
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
# The location where your uploaded files are stored
UPLOAD_LOCATION="/mnt/petrificus totalus/immich/library"
# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release
# Connection secret for postgres. You should change it to a random password
DB_PASSWORD=
# The values below this line do not need to be changed
###################################################################################
DB_HOSTNAME=immich_postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
DB_DATA_LOCATION=./postgres
REDIS_HOSTNAME=immich_redis
After starting the containers with docker-compose up, we can easily access the immich service by going to localhost:2283
After creating an administrator account, you can download the Immich mobile app. The app will ask you to enter your server location. If the server is accessible, you will be asked to log in. After authentication, you will have a Google Photos-like experience with your own storage, without Google pushing you to buy their #cheap
storage plans.
I won't go into how to use Immich because it's similar to Google Photos, and the Immich documentation is quite user-friendly.
Now we need to add a proxy to access Immich using a domain name. To do this, follow the steps in the previous article. Create a subdomain of your choice, for example, immich.example.com.
The proxy configuration will look like this. We use "immich-server" as the hostname because both Nginx and Immich are on the same network. With Docker, the container's hostname will be the service name defined in the docker-compose file.
This allows Nginx to easily send requests to immich-server:3001 when the request comes from immich.donthavemoney.com.
Jellyfin
Jellyfin is a media hosting service that continues to impress me with its capabilities. Let's get straight to setting it up.
The docker-compose file needed to set up Jellyfin is straightforward, so we will add its services directly into the nginx compose file.
version: '2.2'
services:
nginxproxymanager:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginxproxymanager
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./nginx/data:/data
- ./nginx/letsencrypt:/etc/letsencrypt
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
ports:
- 8096:8096
- 8920:8920
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
volumes:
- ./jellyfin/config:/config
- ./jellyfin/tvshows:/data/tvshows
- "/path/to/your/Anime:/data/anime"
- "/path/to/your/movies:/data/movies"
restart: unless-stopped
networks:
default:
name: homelab_network
external: True
So, all you need to do is add the Jellyfin service to the existing Nginx service. Another important task is creating a bind map of your local media directories to the /data directory of the container. Since Jellyfin is inside the same Docker Compose file, we can create reverse proxies similarly.
This is what Jellyfin looks like. Some of the features I absolutely love about Jellyfin are:
Sync play. You can add guest users and sync play between multiple devices and users
All the watched media and last viewed times are saved.
We can control user access and multiple users can consume the same library
So basically my movie and anime collection can be shared and used as my own personal Netflix
A smooth mobile app
This concludes my blog series on creating your own home lab. While it may sound fancy and complicated, a home lab is indeed fancy, but not that complicated. I loved doing all this when I first got into it. I even got my first domain name specifically for this purpose.
From here onwards, it's all about exploring other open-source tools and experimenting using your own computer. For example, you can start by setting up your own GitLab, setting up Pi-hole for network-wide ad blocking., Home automation with Home Assistant or Home bridge and many more. You can even go as far as setting up everything using Kubernetes, which I don't know anything about.
In conclusion, setting up a basic home lab helps you build a solid foundation on Linux, computer networking and some amount of DevOps.