diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2407c13
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# wg-selfserve
+
+## Prerequisites
+
+The tested setup is to host the service on apache, with uwsgi running the
+python application. Example configs for apache and uwsgi are provided in the
+`examples/` subdirectory.
+
+All python dependencies are listed in `requirements.txt`. It is recommended to
+run the application in a virtualenv.
+
+Wireguard must be installed with the `wg` binary available in `$PATH`.
+
+You will need to register the service with an oauth server,
+probably `toker.dsv.su.se`. Oauth settings are saved in `config.ini` along
+with all other settings.
+
+## Setup
+
+ - Clone the repo
+ - Create server keys:  
+   `wg genkey | tee server-priv.key | wg pubkey > server-pub.key`
+ - Create a suitable directory for user client data:  
+   `mkdir user-data`
+ - Set up config.ini:  
+   `cp config.ini.example config.ini && editor config.ini`  
+   The comments in the file should explain each option.
+ - Ensure the web server user can write to the `work/` subdirectory:  
+   `chown www-data work/`
+ - Configure apache and uwsgi, see examples under `examples/`.
+ - Start apache and uwsgi
+ - Create a symbolic link to the wireguard server config:
+   `ln -s /path/to/repo/work/<tunnel-id>.conf /etc/wireguard/`
+ - Activate the wg-quick systemd unit:
+   `systemctl enable wg-quick@<tunnel-id>.service`
diff --git a/api/wireguard.py b/api/wireguard.py
index 95060f2..af53417 100644
--- a/api/wireguard.py
+++ b/api/wireguard.py
@@ -152,11 +152,14 @@ class WireGuard:
         with open(config['server_pubkey_file'], 'r') as pubkey_file:
             self.server_pubkey = pubkey_file.read().strip()
 
-        self.wg_updated = False
-
         self.user_name = None
         self.user_base = None
 
+        # Ensure a wg config exists on startup
+        self.wg_updated = True
+        self.update()
+
+
     def log(self, context_id: str, message) -> None:
         syslog(f'[{self.tunnel_id}] {context_id}: {message}')
 
@@ -327,4 +330,5 @@ class WireGuard:
 
         # Sync updated settings to interface
         run_command('reload')
+        self.wg_updated = False
         return
diff --git a/examples/apache.conf b/examples/apache.conf
new file mode 100644
index 0000000..95d5539
--- /dev/null
+++ b/examples/apache.conf
@@ -0,0 +1,21 @@
+<VirtualHost *:80>
+    ServerName wireguard.example.com
+    Redirect / https://wireguard.example.com/
+</VirtualHost>
+
+<VirtualHost *:443>
+    ServerName wireguard.example.com
+    SSLEngine on
+
+    DocumentRoot /var/www/wg-selfserve/public
+    <Directory /var/www/wg-selfserve/public>
+        Require all granted
+    </Directory>
+
+    RewriteEngine on
+    Rewritecond %{REQUEST_URI} !^/api
+    RewriteCond %{REQUEST_URI} !^/static
+    RewriteRule . index.html [L]
+
+    ProxyPass /api unix:/run/uwsgi/app/wg-selfserve/socket|uwsgi://wg-selfserve/
+</VirtualHost>
diff --git a/examples/uwsgi.ini b/examples/uwsgi.ini
new file mode 100644
index 0000000..1f058d7
--- /dev/null
+++ b/examples/uwsgi.ini
@@ -0,0 +1,24 @@
+[uwsgi]
+plugin = python3
+socket = 127.0.0.1:5000
+processes = 4
+threads = 2
+
+wsgi-file = application.wsgi
+callable = app
+umask = 022
+
+
+# Settings above this line should be safe to reuse unchanged.
+# Below settings may need tweaking.
+
+# Where the repo root is located
+application_base = /var/www/wg-selfserve
+
+# The name of the directory under chdir where the virtualenv is stored
+virtualenv = env
+
+
+# Settings below this line should be left as they are.
+chdir = %(application_base)
+exec-pre-app = rm -f %(application_base)/work/lockfile.lock~