Set up your own node
Complete step-by-step guide to spin up your own MILITAR node: a mailbox that stores end-to-end encrypted messages and files. Not even you, as the operator, can read anything.
What a node is
A — Quick install with script (1 line)
The node runs on a LINUX VPS (Ubuntu/Debian). SSH from your computer (Windows PowerShell, Linux or Mac) and paste the command. The script does everything automatically.
ssh root@IP_DE_TU_VPS
curl -sS https://militar.chat/builds/install-node.sh | bash
Run it as root on a fresh Ubuntu/Debian VPS. It installs everything automatically: downloads milnode.py, creates the user, sets up systemd and the firewall. Then you just need to save the adminSecret and configure HTTPS. If you prefer step by step, follow steps a-h below.
Your node ALREADY works with this
It is reachable at http://YOUR_IP:8780 and you can already register it. The script does NOT install HTTPS, and that is not an oversight: HTTPS needs a domain, and the domain is created afterwards. It is an OPTIONAL step (section g). Without it your messages are still end-to-end encrypted.
B — Step by step (do it yourself)
Same result as the script, but running each command manually. So you see exactly what gets installed and how it works.
An encrypted mailbox, nothing more
A node is a mailbox that stores end-to-end ENCRYPTED messages and files, separated per user. The node operator CANNOT read anything: it only holds sealed blobs. It is a single Python file (milnode.py), with no external dependencies, with its own SQLite database (node.sqlite). Setting it up takes minutes.
Requirements
The bare minimum
Linux VPS with a public IP.
Minimum 1 vCPU, 1 GB of RAM and 20 GB of disk.
Python 3.8 or higher (usually preinstalled on most Linux distributions).
Port 8780 reachable from the Internet.
Detailed steps
a) Get a Linux VPS
Rent a Linux virtual server (for example Ubuntu Server or Debian) with a public IP from any provider. Any modest plan is more than enough.
b) Place the node file
Copy the node file to the path /opt/milnode/milnode.py on the server. It is a single Python file, with no dependencies to install.
mkdir -p /opt/milnode
wget -O /opt/milnode/milnode.py https://militar.chat/builds/milnode.py.txt
c) Run it once by hand
Run the node manually the first time:
python3 /opt/milnode/milnode.py 8780 /opt/milnode/data
This command creates the data folder, generates the node.sqlite file and prints an adminSecret. Store that secret in a safe place: it gives you administrative access to the node.
d) Create a systemd service
So the node starts on its own and restarts if it fails, create a systemd service. For security, do NOT run it as root: first create an unprivileged user and give it ownership of the node folder:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin milnode
sudo chown -R milnode:milnode /opt/milnode
Then define the service with that user:
[Unit]
After=network.target
[Service]
WorkingDirectory=/opt/milnode
ExecStart=/usr/bin/python3 /opt/milnode/milnode.py 8780 /opt/milnode/data
Restart=always
User=milnode
[Install]
WantedBy=multi-user.target
Then enable and start it with: systemctl enable --now milnode
e) Open the firewall
Allow SSH (so you are not locked out) and the node port. IMPORTANT: always port 22 before enabling ufw.
ufw allow 22/tcp
ufw allow 8780/tcp
ufw enable
With 8780 open your node is reachable as http://YOUR_IP:8780 — enough to register and use it even without a domain. If you later add HTTPS with a domain (step g), you can close it with: ufw delete allow 8780/tcp
f) Check the node health
Verify the node responds:
curl http://TU_IP:8780/health
It should return something like: {"ok":true,"version":"3.0.0",...}. If you see it, the node is alive.
g) HTTPS with a domain (OPTIONAL — the node already works without it)
The quick-install script does NOT do this step, because HTTPS needs a domain and the domain is created here. Do it only if you want your node to answer at https://yourdomain instead of http://YOUR_IP:8780.
For real use, assign a domain and put a reverse proxy with HTTPS in front of the node (for example caddy or nginx). This way traffic between the app and the node travels TLS-encrypted on top of the end-to-end encryption of the content.
1. DNS. Point a (sub)domain to your VPS IP at your DNS provider: an A record to the IPv4 and, if you have it, an AAAA to the IPv6. Let's Encrypt issues certificates for domains, not for bare IPs.
2. Install Caddy.
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
3. Configure the proxy. Edit /etc/caddy/Caddyfile and set it like this (replace nodo.tudominio.com with yours):
nodo.tudominio.com {
reverse_proxy 127.0.0.1:8780
}
Reload Caddy (it will fetch the certificate on the first run):
systemctl reload caddy
4. Firewall. ONLY if you already have Caddy with a domain: allow SSH and HTTP/HTTPS, and close 8780 (Caddy reaches it locally). If you do NOT have a domain, leave 8780 open or your node will be unreachable. IMPORTANT: allow port 22 (SSH) BEFORE enabling ufw or you will lose server access.
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
# y solo si YA funciona el HTTPS:
ufw delete allow 8780/tcp
5. Verify.
curl https://nodo.tudominio.com/health
It should return the health JSON over HTTPS. From now on your node URL is https://nodo.tudominio.com — that is the one registered in the network.
h) Register the node in the network
Finally, join your node to the network: send its URL to MILITAR or configure it in the app. From then on users will be able to choose your node as a mailbox.
How it works inside
Directory, deposit and pickup
The central server acts as a DIRECTORY: it stores which node hosts each user and a public depositToken. Other users deposit encrypted messages in the recipient mailbox using that public token. The mailbox owner picks up their messages with their secret ownerToken, which only lives inside their app and never leaves it. Default quotas: 8 GB per user and files up to 5 MB.
Privacy
The node only stores end-to-end encrypted blobs. Neither the operator nor anyone else can read their content: without the recipient private key, which never leaves their device, the data is unreadable.
Trust guarantees
You don't have to trust the operator
Confidentiality is guaranteed by cryptography, not by good faith: the node only stores end-to-end encrypted envelopes. The operator cannot read or forge anything, whoever they are.
Automatic monitoring (watchdog)
The hub probes each node every 10 minutes: it checks it responds and also deposits a test envelope and verifies the node returns it intact. A node that is down, or that loses or tampers with what was deposited, is disabled automatically and stops being offered; if it recovers, it comes back on its own.
Community rating (1–5 stars)
Users rate each node from 1 to 5 stars (one editable vote per person). The watchdog measures the objective side —availability and honesty— and the stars the subjective side —the real experience—. Besides, each user picks their node and can switch anytime: a misbehaving node loses users.