Files
tilde.club/docs/how-to-set-up-a-tilde.md
deepend 367bbafa5f Reworked the main setup guide into a modern, provider-agnostic “build your own tilde” playbook with practical steps for provisioning, SSH hardening, public_html setup, /etc/skel planning, user lifecycle workflows, and operational safety.
Added a structured “add functionality in layers” section (publishing, communication, collaboration, culture) plus a first-week launch checklist to help new operators grow safely and intentionally.
Updated README.md with a clear “start here” section that points operators to the key docs for creating and extending a tilde host.
Updated docs/shellserver.md to point at the new setup guide and introduced a concise “quick priorities” list for new admins.
2026-02-13 18:10:13 +00:00

10 KiB

Build your own tilde-style server (beginner-friendly, step-by-step)

This guide is intentionally detailed for first-time operators.

If you have never run a server before, follow this in order and do not skip ahead.


What you are building

A "tilde-style" host usually provides:

  • A Linux shell account for each user
  • Personal web publishing from ~/public_html
  • Shared Unix tools for learning, writing, coding, and socializing
  • Community norms and moderation

In short: a small, friendly, multi-user Unix community.


0) Before you touch a server

0.1 Buy or prepare these things first

  1. A domain name (example: domain.club)
  2. One Linux server (VPS is fine)
  3. SSH client on your laptop
  4. A text editor you can use comfortably

0.2 Keep this safety rule in mind

Never close your current SSH session until you have confirmed a new SSH session works with your latest config changes.

This one habit prevents most accidental lockouts.


1) Provision your Linux server

You can use AWS, Hetzner, Linode, DigitalOcean, or any other provider.

  • 2 vCPU
  • 4 GB RAM
  • 40 GB SSD
  • Ubuntu LTS or Debian stable (easiest for beginners)

1.1 Point DNS at your server

At your DNS provider:

  • Create an A record for domain.club -> your server IPv4
  • Optionally create AAAA for IPv6

DNS can take time to propagate.

1.2 First login

From your local machine:

ssh root@domain.club

If your provider uses a default admin user (for example ubuntu), use that user and sudo.


2) Base system setup (packages, hostname, firewall)

This section includes both Debian/Ubuntu and Red Hat-family commands.

2.1 Update the system

Debian / Ubuntu

apt update
apt -y upgrade

RHEL / Rocky / Alma / Fedora

dnf -y upgrade

2.2 Install baseline tools

Debian / Ubuntu

apt -y install sudo git curl wget rsync tmux htop vim nano tree jq ufw

RHEL / Rocky / Alma / Fedora

dnf -y install sudo git curl wget rsync tmux htop vim nano tree jq

2.3 Set hostname

hostnamectl set-hostname domain.club

Check:

hostnamectl

2.4 Configure a basic firewall

If using ufw (common on Ubuntu):

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose

If using firewalld (common on RHEL-family):

systemctl enable --now firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-services

3) Create a non-root admin account

Running daily admin tasks as root is risky.

3.1 Create admin user

adduser admin

On some distros:

useradd -m -s /bin/bash admin
passwd admin

3.2 Give sudo privileges

Debian / Ubuntu

usermod -aG sudo admin

RHEL-family

usermod -aG wheel admin

3.3 Test sudo

su - admin
sudo whoami

Expected output: root


4) SSH hardening (safe order, no lockouts)

Do this carefully.

4.1 Set up admin SSH key directory and file

install -d -m 700 /home/admin/.ssh
install -m 600 /dev/null /home/admin/.ssh/authorized_keys
chown -R admin:admin /home/admin/.ssh

4.2 Add your public key

On your local machine, show your public key:

cat ~/.ssh/id_ed25519.pub

Copy that line and paste it into:

/home/admin/.ssh/authorized_keys

Example on server:

printf '%s\n' 'ssh-ed25519 AAAA... your-key-comment' >> /home/admin/.ssh/authorized_keys
chown admin:admin /home/admin/.ssh/authorized_keys
chmod 600 /home/admin/.ssh/authorized_keys

4.3 Keep passwords ON while you test keys

Edit /etc/ssh/sshd_config:

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes

Reload:

systemctl reload sshd

From a second local terminal, test login:

ssh admin@domain.club

If this fails, fix it now. Do not continue.

4.4 Disable password auth only after key login works

Edit /etc/ssh/sshd_config:

PasswordAuthentication no

Reload and test again from a second terminal:

systemctl reload sshd
ssh admin@domain.club

Only after success should you end your old session.


5) Install and configure Apache for user pages

This is the baseline many tilde hosts use for ~username pages.

5.1 Install Apache

Debian / Ubuntu

apt -y install apache2
systemctl enable --now apache2

RHEL-family

dnf -y install httpd
systemctl enable --now httpd

Check service status:

systemctl status apache2 --no-pager
# or
systemctl status httpd --no-pager

5.2 Enable user directories (~username URLs)

Debian / Ubuntu

a2enmod userdir
systemctl restart apache2

By default, this serves /home/USERNAME/public_html as:

http://domain.club/~USERNAME/

RHEL-family

Edit Apache config (often /etc/httpd/conf/httpd.conf) and ensure:

UserDir public_html

<Directory /home/*/public_html>
    AllowOverride All
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS
</Directory>

Then restart:

systemctl restart httpd

5.3 Create a test web user and page

useradd -m -s /bin/bash testuser
mkdir -p /home/testuser/public_html
cat > /home/testuser/public_html/index.html <<'HTML'
<!doctype html>
<html>
  <head><meta charset="utf-8"><title>testuser page</title></head>
  <body><h1>hello from testuser</h1></body>
</html>
HTML
chown -R testuser:testuser /home/testuser
chmod 755 /home/testuser
chmod 755 /home/testuser/public_html
chmod 644 /home/testuser/public_html/index.html

Now test locally on the server:

curl -I http://localhost/~testuser/
curl http://localhost/~testuser/

Then test from your laptop:

curl -I http://domain.club/~testuser/

If it fails, check Apache logs:

Debian / Ubuntu

tail -n 100 /var/log/apache2/error.log

RHEL-family

tail -n 100 /var/log/httpd/error_log

6) Prepare /etc/skel before inviting users

/etc/skel is copied into every new account. Set it up early.

  • .bashrc and/or .zshrc with helpful comments
  • public_html/index.html starter page
  • A README with first commands and local rules
  • Optional public_gemini/ and public_gopher/

6.2 Example starter files

install -d -m 755 /etc/skel/public_html
cat > /etc/skel/public_html/index.html <<'HTML'
<!doctype html>
<html>
  <head><meta charset="utf-8"><title>Welcome</title></head>
  <body>
    <h1>It works!</h1>
    <p>Edit this file to publish your page.</p>
  </body>
</html>
HTML
cat > /etc/skel/README-FIRST.txt <<'TXT'
Welcome to the server.

Useful first commands:
- pwd
- ls -la
- nano ~/public_html/index.html

Your web page lives at:
http://domain.club/~YOURUSERNAME/
TXT

See also: docs/etc-skel-permissions.md.


7) Install baseline user tools

Give new users a capable, friendly default toolbox.

Debian / Ubuntu

apt -y install \
  zsh fish \
  emacs vim nano \
  irssi weechat \
  mutt alpine \
  lynx w3m links \
  git build-essential python3 nodejs npm

RHEL-family

dnf -y install \
  zsh fish \
  emacs vim nano \
  irssi weechat \
  mutt alpine \
  lynx links \
  git gcc make python3 nodejs npm

Add or remove packages based on your community.


8) Add users safely and consistently

Use a repeatable checklist every time.

8.1 Account creation checklist

useradd -m -s /bin/bash USERNAME
passwd -l USERNAME
install -d -m 700 /home/USERNAME/.ssh
install -m 600 /dev/null /home/USERNAME/.ssh/authorized_keys
install -d -m 755 /home/USERNAME/public_html
chown -R USERNAME:USERNAME /home/USERNAME

8.2 Add the user's public key

printf '%s\n' 'ssh-ed25519 AAAA... user@device' >> /home/USERNAME/.ssh/authorized_keys
chown USERNAME:USERNAME /home/USERNAME/.ssh/authorized_keys
chmod 600 /home/USERNAME/.ssh/authorized_keys

8.3 Verify login and web publishing

ssh USERNAME@domain.club
curl -I http://domain.club/~USERNAME/

9) Add "tilde functionality" in manageable layers

Do not launch everything on day one.

Layer A: personal publishing

  • User web pages in public_html
  • Basic HTML templates
  • Optional Gemini and Gopher directories

Layer B: communication

  • IRC client docs
  • Local mail (postfix + local delivery)
  • Server bulletin/MOTD updates

Layer C: collaboration

  • Shared Git repos
  • Local pastebin/snippet service
  • Community docs/wiki process

Layer D: culture and learning

  • New-user orientation checklist
  • Mentoring or office-hours in chat
  • Monthly "show your tilde" events

10) Operations, backup, and recovery

10.1 Back up the important data

At minimum, back up:

  • /home
  • /etc
  • Web server config (/etc/apache2 or /etc/httpd)
  • Mail config if used

10.2 Example nightly backup script

Create /usr/local/sbin/backup-tilde.sh:

#!/usr/bin/env bash
set -euo pipefail

DEST=/var/backups/tilde
DATE=$(date +%F)
mkdir -p "$DEST/$DATE"

tar -czf "$DEST/$DATE/home.tgz" /home
tar -czf "$DEST/$DATE/etc.tgz" /etc

Make executable:

chmod 700 /usr/local/sbin/backup-tilde.sh

Run once manually:

/usr/local/sbin/backup-tilde.sh

Then automate with cron or systemd timers.

10.3 Test restore (critical)

A backup is not real until you test restoring at least one file.


11) First-week launch checklist

  • DNS points to server
  • Firewall allows only intended ports
  • Admin key login works from a second terminal
  • Password auth disabled only after key validation
  • Apache running and ~testuser page reachable
  • /etc/skel tested by creating a new account
  • Backup job ran and one restore test passed
  • Rules/moderation/contact info published
  • At least one backup admin has emergency access

12) Where to continue in this repository

  • docs/shellserver.md for shell host operational notes
  • docs/etc-skel-permissions.md for current skeleton permissions
  • docs/ssh.md for SSH key onboarding details
  • docs/server.org for historical package/setup notes