nixos-dotfiles
nixos-dotfiles
https://git.tonybtw.com/nixos-dotfiles.git
git://git.tonybtw.com/nixos-dotfiles.git
Home Server XMPP Deployment Guide
Complete guide to deploying XMPP on your home server (the laptop downstairs) with Cloudflare DDNS and chat.tonybtw.com.
Overview
What you're building:
- XMPP server (Prosody) on your home laptop
- Domain:
chat.tonybtw.com - Cloudflare DDNS (auto-updates your home IP)
- SSL via Let's Encrypt (DNS challenge)
- Port forwarding on router
- Foundation for future homelab (Jellyfin, Nextcloud, etc.)
Time estimate: 1-2 hours
Prerequisites
- [ ] You own
tonybtw.com - [ ] Your laptop is running NixOS
- [ ] Your laptop is always on (or nearly always)
- [ ] You have access to your router admin panel
- [ ] Your ISP doesn't block ports 80, 443, 5222, 5269, 5281
Step 1: Cloudflare Setup
Follow the cloudflare-setup.md guide completely.
Summary:
- Point
tonybtw.comnameservers to Cloudflare - Add DNS A records for
chat.tonybtw.com - Create API token for DDNS
- Create
/root/secrets/cloudflare-tokenfile - Create
/root/secrets/cloudflare-acme-credentialsfile
Stop here and do that first. Come back when Cloudflare is configured.
Step 2: Router Port Forwarding
Follow the router-portforward-guide.md guide completely.
Summary:
- Find your server's local IP (e.g.,
192.168.1.100) - Set static IP (DHCP reservation)
- Forward ports: 22, 80, 443, 5222, 5269, 5281
- Test ports are open from outside network
Stop here and do that. Come back when port forwarding works.
Step 3: Prepare NixOS Configuration
On your home server (laptop):
cd /etc/nixos
A. Copy Config Files
If you have them in ~/nixos-dotfiles:
sudo cp ~/nixos-dotfiles/home-server-base.nix /etc/nixos/
sudo cp ~/nixos-dotfiles/xmpp-home.nix /etc/nixos/
Or clone from your git repo if you pushed them.
B. Edit Configuration Files
Edit home-server-base.nix:
sudo vim /etc/nixos/home-server-base.nix
Change line 20:
domains = [
"chat.tonybtw.com" # Verify this is YOUR domain
];
Change line 44:
email = "tony@tonybtw.com"; # YOUR email for Let's Encrypt
Edit xmpp-home.nix:
sudo vim /etc/nixos/xmpp-home.nix
Change line 23:
admins = [ "tony@chat.tonybtw.com" ]; # YOUR username
Step 4: Update Main Configuration
Edit your main configuration:
sudo vim /etc/nixos/configuration.nix
Add these imports at the top (in the imports section):
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./home-server-base.nix
./xmpp-home.nix
# ... any other imports you have
];
# Rest of your config...
}
Save and exit.
Step 5: Verify Secrets Files Exist
# Check Cloudflare token
sudo cat /root/secrets/cloudflare-token
# Should show your API token
# Check ACME credentials
sudo cat /root/secrets/cloudflare-acme-credentials
# Should show: CF_DNS_API_TOKEN=your_token
# If missing, go back to cloudflare-setup.md Step 5-6
Step 6: Deploy Configuration
# Build and activate new configuration
sudo nixos-rebuild switch
This will:
- Install Prosody
- Configure firewall
- Set up Cloudflare DDNS service
- Request Let's Encrypt SSL certificates (takes ~60 seconds)
- Start XMPP server
Watch for errors. Common issues:
- Cloudflare API token wrong → Check
/root/secrets/cloudflare-token - ACME certificate fails → Check DNS is pointing to your home IP
- Prosody fails to start → Check logs:
sudo journalctl -u prosody
If successful, you'll see:
building the system configuration...
activating the configuration...
setting up /etc...
reloading the following units: dbus.service
starting the following units: prosody.service, cloudflare-dyndns.service
Step 7: Verify Services Are Running
# Check Prosody
sudo systemctl status prosody
# Should show: active (running)
# Check Cloudflare DDNS
sudo systemctl status cloudflare-dyndns
# Should show: active (running)
# Check ACME certificate
sudo systemctl status acme-chat.tonybtw.com
# Should show: finished successfully
# View Prosody logs
sudo journalctl -u prosody -n 50
# Should show: "Prosody is using the epoll backend for connection handling"
If any service failed:
# See detailed logs
sudo journalctl -u prosody -n 100
sudo journalctl -u acme-chat.tonybtw.com -n 100
Step 8: Create XMPP Admin Account
# Create your admin account
sudo prosodyctl adduser tony@chat.tonybtw.com
# Enter a strong password when prompted
Test it worked:
sudo prosodyctl list:users
# Should show: tony@chat.tonybtw.com
Step 9: Test XMPP Connection (Local)
Install an XMPP client on your laptop:
nix-shell -p dino
Open Dino:
- Click "Add Account"
- Jabber ID:
tony@chat.tonybtw.com - Password: (the one you just set)
- Click "Connect"
Expected result: Green indicator, "Connected"
If connection fails:
- Check Prosody is running:
sudo systemctl status prosody - Check firewall allows 5222:
sudo iptables -L -v | grep 5222 - Check logs:
sudo journalctl -u prosody -f
Step 10: Test XMPP Connection (External)
From another network (phone on mobile data, or friend's computer):
-
Install XMPP client:
- Android: Conversations
- iOS: Monal
- Desktop: Gajim or Dino
-
Add account:
- Jabber ID:
tony@chat.tonybtw.com - Password: (your password)
- Jabber ID:
-
Connect
Expected result: Connection successful
If connection fails:
- Check ports are forwarded: Use https://www.yougetsignal.com/tools/open-ports/ to test port 5222
- Check DNS resolves:
dig chat.tonybtw.comshould show your home IP - Check Cloudflare proxy is DISABLED (gray cloud, not orange)
Step 11: Test SSL Certificate
# Test SSL certificate
openssl s_client -connect chat.tonybtw.com:5222 -starttls xmpp
# Should show certificate details and:
# Verify return code: 0 (ok)
If certificate is invalid:
# Check ACME logs
sudo journalctl -u acme-chat.tonybtw.com
# Manually renew if needed
sudo systemctl start acme-chat.tonybtw.com
Step 12: Create User Accounts for Friends
# Create accounts
sudo prosodyctl adduser alice@chat.tonybtw.com
sudo prosodyctl adduser bob@chat.tonybtw.com
sudo prosodyctl adduser charlie@chat.tonybtw.com
# List all users
sudo prosodyctl list:users
Step 13: Create Group Rooms
In Dino (or any XMPP client), logged in as your admin account:
-
Join/Create Room:
- Address:
#general@conference.chat.tonybtw.com - Click "Join"
- Room will be auto-created
- Address:
-
Make Room Persistent:
- In Dino: Right-click room → "Configure Room"
- Enable "Persistent" and "Public"
- Save
-
Create more rooms:
#random@conference.chat.tonybtw.com#tech@conference.chat.tonybtw.com#gaming@conference.chat.tonybtw.com
Step 14: Invite Friends
Send each friend:
-
Their credentials:
Username: yourname@chat.tonybtw.com Password: [their_password] -
The setup guide: Share
xmpp-setup.md(edit it first to replaceyourdomain.comwithchat.tonybtw.com) -
Room to join:
#general@conference.chat.tonybtw.com
Maintenance
View Logs
# Prosody logs
sudo journalctl -u prosody -f
# DDNS logs
sudo journalctl -u cloudflare-dyndns -f
# System logs
sudo journalctl -f
Restart Services
sudo systemctl restart prosody
sudo systemctl restart cloudflare-dyndns
Manage Users
# Add user
sudo prosodyctl adduser newuser@chat.tonybtw.com
# Change password
sudo prosodyctl passwd username@chat.tonybtw.com
# Delete user
sudo prosodyctl deluser olduser@chat.tonybtw.com
# List users
sudo prosodyctl list:users
Check Server Status
# Prosody status and stats
sudo prosodyctl about
# Connected users
sudo prosodyctl mod_admin_telnet
# Then type: c2s:show()
# Exit with: quit
Renew SSL Certificates
Automatic renewal happens via systemd timer. Check status:
# Check ACME timer
sudo systemctl list-timers | grep acme
# Manually renew
sudo systemctl start acme-chat.tonybtw.com
Troubleshooting
Prosody Won't Start
# Check config syntax
sudo prosodyctl check config
# Check certificate permissions
sudo ls -la /var/lib/acme/chat.tonybtw.com/
# Should be readable by prosody user
sudo chown -R prosody:prosody /var/lib/acme/chat.tonybtw.com/
Can't Connect from External Network
# Check if ports are actually open (from another network):
nc -zv YOUR_HOME_IP 5222
# Check DNS resolution:
dig chat.tonybtw.com
# Should show your home IP
# Check Cloudflare DDNS is updating:
sudo journalctl -u cloudflare-dyndns | tail -20
# Check your current home IP:
curl ifconfig.me
SSL Certificate Failed
# View ACME logs
sudo journalctl -u acme-chat.tonybtw.com -n 100
# Common issues:
# 1. DNS not pointing to your IP yet (wait 10 minutes)
# 2. Cloudflare API token wrong (check /root/secrets/cloudflare-acme-credentials)
# 3. Rate limit (Let's Encrypt allows 5 certs/week)
# Retry manually:
sudo systemctl start acme-chat.tonybtw.com
Home IP Changed But DNS Not Updating
# Check DDNS service
sudo systemctl status cloudflare-dyndns
# Manually trigger update
sudo systemctl restart cloudflare-dyndns
# Check Cloudflare dashboard
# Go to Cloudflare → DNS → Records
# Verify "chat" A record shows current IP
Backup Strategy
What to backup:
- User accounts and messages:
/var/lib/prosody/ - SSL certificates:
/var/lib/acme/ - Configuration:
/etc/nixos/
Simple Backup Script:
#!/usr/bin/env bash
# /root/backup-homelab.sh
BACKUP_DIR="/home/tony/backups"
DATE=$(date +%Y%m%d-%H%M)
mkdir -p $BACKUP_DIR
# Backup Prosody data
sudo tar czf $BACKUP_DIR/prosody-$DATE.tar.gz /var/lib/prosody/
# Backup configs
sudo tar czf $BACKUP_DIR/nixos-$DATE.tar.gz /etc/nixos/
# Keep last 30 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
echo "Backup complete: $BACKUP_DIR"
Make it executable:
sudo chmod +x /root/backup-homelab.sh
Automate with systemd timer:
# Add to configuration.nix
systemd.timers.homelab-backup = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
systemd.services.homelab-backup = {
serviceConfig.ExecStart = "/root/backup-homelab.sh";
};
Then: sudo nixos-rebuild switch
Next Steps (Homelab Expansion)
Once XMPP is running, you can add more services:
Jellyfin (Media Server):
services.jellyfin = {
enable = true;
openFirewall = true;
};
# Access at: http://your-server-ip:8096
# Later: Set up jellyfin.tonybtw.com with Nginx reverse proxy
Nextcloud (File Sync/Share):
services.nextcloud = {
enable = true;
hostName = "cloud.tonybtw.com";
config.adminpassFile = "/root/secrets/nextcloud-admin-pass";
};
Vaultwarden (Password Manager):
services.vaultwarden = {
enable = true;
config = {
domain = "https://vault.tonybtw.com";
signupsAllowed = false;
};
};
All of these will use:
- Same Cloudflare DDNS setup
- Same router port forwarding (or Nginx reverse proxy)
- Same Let's Encrypt SSL certificates
Your XMPP setup is the foundation. Everything else builds on top.
Monitoring
Check Disk Space:
df -h
ncdu / # Interactive disk usage
Check Memory:
free -h
htop
Check Uptime:
uptime
Check Network:
# Current connections
sudo ss -tunap | grep prosody
# Bandwidth usage (install iftop)
sudo nix-shell -p iftop
sudo iftop
Security Checklist
- [ ] Fail2ban is running:
sudo systemctl status fail2ban - [ ] Firewall is enabled:
sudo iptables -L -v - [ ] SSH has strong password or key-only auth
- [ ] Root login is disabled
- [ ] Prosody admin account has strong password
- [ ] SSL certificates are valid
- [ ] Router admin password is changed from default
- [ ] Only necessary ports are forwarded
You're Done!
Your home XMPP server is now running at chat.tonybtw.com.
Share with friends: Give them xmpp-setup.md (updated with your domain)
Future additions:
- Jellyfin for media streaming
- Nextcloud for file sync
- Nginx reverse proxy for web services
- Monitoring (Grafana + Prometheus)
Welcome to self-hosting. You now control your communication infrastructure. 🎉
Quick Reference Commands
# Restart XMPP
sudo systemctl restart prosody
# View XMPP logs
sudo journalctl -u prosody -f
# Add user
sudo prosodyctl adduser user@chat.tonybtw.com
# List users
sudo prosodyctl list:users
# Check server status
sudo prosodyctl about
# Update system
sudo nixos-rebuild switch --upgrade
# Check open ports
sudo ss -tulpn