Grafinya
Contents
  1. Requirements
  2. Connect via SSH
  3. Ports and firewall
  4. Install Docker
  5. Download the panel
  6. Start
  7. Access: HTTP or HTTPS
  8. First-run setup
  9. Client and .conf file
  10. Connect on iPhone
  11. Updating
  12. Backup
  13. Uninstall
  14. Troubleshooting
Guide

Installing Grafinya Panel

Step by step: from an empty VPS to a connected iPhone. Takes 15–20 minutes, about 5 of which is building the image.

Enter your server IP (and domain, if you have one) — the commands below will use them. The values stay in your browser only.

1Requirements

  • A VPS with a public IPv4 from any provider: Ubuntu 22.04 / 24.04 or Debian 12.
  • 1 GB RAM or more, ~5 GB of free disk space (the image is built on the server).
  • root access or a user with sudo.
  • Open ports 51820/udp (VPN) and 51821/tcp (web panel).
  • Optional: a domain, if you want HTTPS for the panel (recommended).
PortPurpose
51820/udpVPN tunnel (Grafinya core)
51821/tcpweb panel
80, 443/tcponly if you set up HTTPS with Caddy

2Connect via SSH

On macOS and Linux open Terminal, on Windows — PowerShell or Windows Terminal. Your provider sends the IP and root password once the server is created.

terminal
ssh root@SERVER_IP

Answer yes to the host key fingerprint prompt on first connect. If you are not logged in as root, prefix the commands below with sudo or run sudo -i.

update the system (recommended)
apt update && apt upgrade -y

3Ports and firewall

Ports must be open in two places: in your provider’s control panel (cloud security group / firewall, if any) and on the server itself if ufw is enabled.

ufw
ufw allow OpenSSH
ufw allow 51820/udp
ufw allow 51821/tcp
ufw enable
ufw status
Don’t lock yourself out. ufw allow OpenSSH must come before ufw enable. If SSH runs on a custom port, allow that port.
Note on Docker. Published Docker ports bypass ufw rules. To hide the panel from the internet, closing 51821 in ufw is not enough — bind the port to 127.0.0.1 (see step 7, HTTPS option) or close it in the provider firewall.

4Install Docker

The official script installs Docker Engine and the docker compose plugin:

terminal
curl -fsSL https://get.docker.com | sh
check
docker --version
docker compose version

5Download the panel from GitHub

Option A — git (easy updates)

terminal
apt install -y git
git clone https://github.com/grapelloid/grafinya-panel.git && cd grafinya-panel

Option B — ZIP archive

Without git: download the branch archive from GitHub and unpack it on the server.

terminal
apt install -y curl unzip
curl -L -o grafinya-panel.zip https://github.com/grapelloid/grafinya-panel/archive/refs/heads/main.zip
unzip grafinya-panel.zip && cd grafinya-panel-main

With option B you update the same way — by downloading a new archive. Your data is safe: it lives in a Docker volume, not in the folder.

6Start

There is no prebuilt image in a registry — it is built from source on your server. The first build takes 3–10 minutes: the Grafinya core is compiled.

terminal
docker compose up -d --build

Check that the grafinya container is running (status Up, and healthy after a minute):

terminal
docker ps

Follow the logs (exit with Ctrl+C, the container keeps running):

terminal
docker logs -f grafinya
Traffic masking is on by default. Its parameters are generated on first start — nothing to configure.

7Panel access: HTTP for testing or HTTPS

By default the panel expects HTTPS: you can’t sign in over plain http:// (session cookies are secure-only). Pick one option.

Option A — quick, over HTTP (testing)

Open docker-compose.yml (e.g. nano docker-compose.yml), uncomment the environment block and set INSECURE=true:

docker-compose.yml
services:
  grafinya:
    environment:
      - INSECURE=true
apply
docker compose up -d

The panel is now at http://SERVER_IP:51821.

Testing only. Over HTTP the admin login and password travel in clear text. For everyday use, set up a domain and HTTPS.

Option B — domain and HTTPS with Caddy (recommended)

  1. At your DNS provider, create an A record panel.example.com → SERVER_IP and wait for it to resolve.
  2. Open ports 80 and 443: ufw allow 80/tcp && ufw allow 443/tcp (and in the provider firewall).
  3. Install Caddy — it obtains and renews a free TLS certificate automatically:
install Caddy
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl gpg
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

Replace the contents of /etc/caddy/Caddyfile:

/etc/caddy/Caddyfile
panel.example.com {
    reverse_proxy 127.0.0.1:51821
}
apply
systemctl reload caddy

To make the panel reachable only over HTTPS, bind port 51821 to localhost in docker-compose.yml and restart the container (keep INSECURE at false):

docker-compose.yml
    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
apply
docker compose up -d
ufw delete allow 51821/tcp

The panel now opens at https://panel.example.com.

8First-run setup

On first visit the panel walks you through a setup wizard:

  1. Welcome → “Continue”.
  2. Administrator: a username and a strong password — at least 12 characters. Store it in a password manager.
  3. Existing setup? — “No” (unless you are restoring from a backup of an old server).
  4. That’s it: the server’s public address and VPN port 51820/udp are filled in automatically. Change them in the admin area (Configuration and Interface); the port must match ports: in docker-compose.yml.

In the admin area you can enable 2FA and adjust interface and traffic masking settings.

Grafinya Panel sign-in screen
Panel sign-in — light “squared notebook” theme.

9Create a client and download .conf

  1. On the Clients page click “New client”.
  2. Enter a name (e.g. “My iPhone”). Leave the expiry date empty for unlimited access; to extend access, just change the date.
  3. Click “Create client”.
  4. On the client card click the down-arrow button — “Download configuration”. You get a .conf file.
Client list in Grafinya Panel
Client list: enable/disable, QR code, .conf download and one-time link.

Moving the file to your iPhone

  • AirDrop — from a Mac straight to the iPhone, then “Save to Files”.
  • Files / iCloud Drive — put the file in iCloud Drive on your computer; it shows up in the Files app.
  • Email or messenger — send it to yourself and save the attachment to Files.
  • Or open the panel in Safari on the iPhone and download the file — it lands in Files → Downloads.
A .conf file is a key. It contains the client’s private key: don’t publish it or share it in group chats. One client — one device.

10Connect in the grafinya app

  1. Open grafinya and tap “Choose file”.
  2. Pick your .conf in Files.
  3. Flip the switch. On first connect iOS asks to allow adding a VPN configuration — tap “Allow”.
  4. We recommend turning on Kill Switch: Settings → Security. If the tunnel drops, internet access is blocked and your real IP won’t leak.

Check: open any “what is my IP” service in Safari — it should show your server’s IP. The panel shows the client as online with traffic counters.

More about the app →

11Updating

terminal
cd ~/grafinya-panel
git pull
docker compose up -d --build

The database, keys and settings live in the panel’s Docker volume and survive rebuilds. Clean up old images with docker image prune -f.

12Backup

All panel data is in the grafinya-panel_grafinya_data Docker volume (the name is fixed and doesn’t depend on the folder you cloned into). Archive it:

backup
cd ~/grafinya-panel
docker compose stop
docker run --rm -v grafinya-panel_grafinya_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/grafinya-backup-$(date +%F).tar.gz -C /data .
docker compose start

Copy the archive to your computer (run this on your computer, not on the server):

on your computer
scp root@SERVER_IP:~/grafinya-panel/grafinya-backup-*.tar.gz .

To restore on a new server, install the panel with steps 4–6, then:

restore
docker compose stop
docker run --rm -v grafinya-panel_grafinya_data:/data -v "$PWD":/backup alpine \
  sh -c "rm -rf /data/* && tar xzf /backup/grafinya-backup-DATE.tar.gz -C /data"
docker compose start
The archive contains server and client private keys. Keep it as safe as your passwords.

13Uninstall

Stop and remove the container, keeping the data:

terminal
cd ~/grafinya-panel
docker compose down

Remove everything, including the database, keys and all clients (irreversible):

terminal
cd ~/grafinya-panel
docker compose down -v --rmi all
cd ~ && rm -rf ~/grafinya-panel

14Troubleshooting

The panel doesn’t open at http://IP:51821
  • Make sure the container is running: docker ps, and check docker logs grafinya.
  • Port 51821/tcp is closed in the provider’s security group / firewall — the most common cause. Open it in the provider’s control panel.
  • Test locally on the server: curl -I http://127.0.0.1:51821. If it answers locally but not from outside, it’s the firewall.
The page opens but I can’t sign in

You’re using HTTP without INSECURE=true. Enable it (step 7, option A) or set up HTTPS (option B).

The switch turns on but there’s no internet
  • 51820/udp is closed — in ufw or the provider firewall. It’s UDP, not TCP.
  • The wrong host was entered in the setup wizard: configs must contain the server’s public IP/domain. Fix it in the admin area and download the .conf again.
  • The client is disabled or expired in the panel — enable it or change the date.
  • The VPS provider blocks non-standard UDP — try another port (change it both in the panel and in ports in docker-compose.yml).
The app says the file is not valid

It needs a file with the .conf extension and [Interface] and [Peer] sections. Download it with “Download configuration” in the panel rather than copying text.

Forgot the admin password

Reset it from the server console (at least 12 characters; 2FA is reset too):

terminal
docker exec -it grafinya cli db:admin:reset
The image build fails or the server freezes

Most likely it ran out of memory while compiling. Add 1–2 GB of swap and run docker compose up -d --build again:

terminal
fallocate -l 2G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Still stuck? Open an issue on GitHub — attach the output of docker logs grafinya (without keys or passwords).