nixos-dotfiles

nixos-dotfiles

https://git.tonybtw.com/nixos-dotfiles.git git://git.tonybtw.com/nixos-dotfiles.git
13,107 bytes raw

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:

  1. Point tonybtw.com nameservers to Cloudflare
  2. Add DNS A records for chat.tonybtw.com
  3. Create API token for DDNS
  4. Create /root/secrets/cloudflare-token file
  5. Create /root/secrets/cloudflare-acme-credentials file

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:

  1. Find your server's local IP (e.g., 192.168.1.100)
  2. Set static IP (DHCP reservation)
  3. Forward ports: 22, 80, 443, 5222, 5269, 5281
  4. 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:

  1. Install Prosody
  2. Configure firewall
  3. Set up Cloudflare DDNS service
  4. Request Let's Encrypt SSL certificates (takes ~60 seconds)
  5. 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:

  1. Click "Add Account"
  2. Jabber ID: tony@chat.tonybtw.com
  3. Password: (the one you just set)
  4. 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):

  1. Install XMPP client:

    • Android: Conversations
    • iOS: Monal
    • Desktop: Gajim or Dino
  2. Add account:

    • Jabber ID: tony@chat.tonybtw.com
    • Password: (your password)
  3. Connect

Expected result: Connection successful

If connection fails:


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:

  1. Join/Create Room:

    • Address: #general@conference.chat.tonybtw.com
    • Click "Join"
    • Room will be auto-created
  2. Make Room Persistent:

    • In Dino: Right-click room → "Configure Room"
    • Enable "Persistent" and "Public"
    • Save
  3. 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:

  1. Their credentials:

    Username: yourname@chat.tonybtw.com
    Password: [their_password]
  2. The setup guide: Share xmpp-setup.md (edit it first to replace yourdomain.com with chat.tonybtw.com)

  3. 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