tilde is an effort to automagically deploy a homeserver with a few useful services using pyinfra. While it's built for personal use cases in mind, it's general enough to be used by anyone. Expect breaking changes :)
- A Wireguard tunnel with a user-friendly interface so you can access your services even when you're not home, without exposing them to the internet.
- Dynamic DNS using DuckDNS so that wireguard can always connect you to your services
- A Nextcloud instance for your own cloud storage
- A Jellyfin instance for media consumption
- A Nginx Proxy Manager Instance for reverse proxy and TLS (Configured by the user)
While tilde is meant to be very hands off, there's still a few things you'll need to do manually. It's not incredibly complicated, but the instructions are written under the assumption that you're at least a little bit familiar with unix commandline.
- A machine running Debian 12 or above (for future)
- SSH access with a non-root user
- Sudo privileges for the non-root user
If you don't have ssh keys set up, please take a look at the Github Docs on the topic.
Your ssh config should should look something like this if you're on MacOS:
# .ssh/config
host <homeserver>
HostName <internal-ip-of-server>
user <non-root-user>
host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Replace <homeserver>, <internal-ip-of-server>, and <non-root-user> with the appropriate values (without the < >)
NOTE: This is for your personal machine, NOT for the server.
If you're on a different OS, the Github guide has instructions for windows and linux as well, I trust that you'll be able to follow them :)
In order for the Wireguard tunnel to work, you'll need to set up port forwarding on your home router. The instructions can vary from router to router so there are no specific instructions on how to do so.
Once you've figured out how to do so, forward port 51820
to port 51820
of your homeserver.
With a residential internet connection, your public IP is liable to change at any given moment. This is why you'll need to set up Dynamic DNS to make sure the Wireguard tunnel can still connect you to your home network even if your public IP changes.
tilde uses ZenDNS to periodically update the DNS records. While this guide assumes that DuckDNS will be used, ZenDNS also works with Cloudflare and Namecheap. Please read the docs for ZenDNS to configure what works best for you.
Assuming you're using DuckDNS:
- Sign up for an account
- Pick a new subdomain on the website and click
add domain
- Copy the
token
from the website as well
Fill out the information in src/tilde/templates/zendns.yaml.j2. It should look something like:
duckdns:
- token: "your-token"
domain: "your-subdomain.duckdns.org"
Again, look at the docs for ZenDNS and replace the contents of src/tilde/templates/zendns.yaml.j2 with configuration for your chosen provider.
As the final step of preparation, you'll need to fill out some environment variables in the run script.
# run.sh
export USERNAME=<non-root-user>
export HOST=<homeserver-from-your-ssh-config>
export WIREGUARD_PASSWORD=<password-you-want-for-wireguard-ui>
export WIREGUARD_HOST=<your-subdomain.duckdns.org>
Without the < >
Phew that was a lot!! But we're finally ready to deploy!
tilde only has one dependency: pyinfra
. You can either use uv like I do, or just use a venv and install pyinfra
yourself, it's totally up to you!
uv sync # Create a virutal environment and install pyinfra
source .venv/bin/activate # Activate the virutal environment
./run.sh # Run tilde on your homeserver
python3 -m venv tilde_venv # Create a venv for tilde
source tilde_venv/bin/activate # Activate the venv
pip3 install pyinfra # Install pyinfra and dotenv
./run.sh # Run tilde on your homeserver
If everything goes as expected, you'll have a shiny new homeserver complete with all the features mentioned earlier!
The services are available at homeserver-internal-ip:service-port
The mapping for the ports is as follows:
nginx: 81
nextcloud: 8080
jellyfin: 8096
wireguard: 51821
Feel free to use Nginx Proxy Manager to set up internal domains for these services
0.5.0 - Update to pyinfra v3 and use zendns