diff --git a/etc/nixos/configuration.nix b/etc/nixos/configuration.nix
index b6eef7d..fb9f09e 100644
--- a/etc/nixos/configuration.nix
+++ b/etc/nixos/configuration.nix
@@ -56,65 +56,28 @@
   };
 
   docker-containers = {
-    ## nginx proxy
-    nginx-proxy = {
-      image = "jwilder/nginx-proxy:alpine";
-      ports = [
-        "80:80"
-        "443:443"
-      ];
-      volumes = [
-        # So that we can watch new containers come up
-        "/var/run/docker.sock:/tmp/docker.sock:ro"
-        # So that we can access generated certs
-        "nginx-certs:/etc/nginx/certs:ro"
-        # So that we can write challenge files for letsencrypt auth
-        "nginx-challenges:/usr/share/nginx/html"
-        # So that we can modify config on-the-fly to set up challenge
-        # files
-        "nginx-conf:/etc/nginx/vhost.d"
-      ];
-      environment = {
-        DHPARAM_GENERATION = "false"; # Provided by nginx-proxy-letsencrypt
-      };
-      extraDockerOptions = [
-        "--network=webproxy"
-      ];
-    };
+    ## Reverse proxy
+    #
+    # These two services set up a reverse proxy that allows setting up
+    # SSL services with docker containers on subdomains easily.
+    #
+    # To use, simply set:
+    #
+    # ```nix
+    # environment = {
+    #     VIRTUAL_HOST = "<subdomain>.tlater.net";
+    #     LETSENCRYPT_HOST = "<subdomain>.tlater.net";
+    # }
+    # extraDockerOptions = [
+    #     "--network=webproxy"
+    # ];
+    # ```
+    nginx-proxy = import ./services/nginx-proxy.nix;
+    nginx-proxy-letsencrypt = import ./services/nginx-proxy-letsencrypt.nix;
 
-    nginx-proxy-letsencrypt = {
-      image = "jrcs/letsencrypt-nginx-proxy-companion";
-      volumes = [
-        "/var/run/docker.sock:/var/run/docker.sock:ro"
-        "nginx-certs:/etc/nginx/certs"
-      ];
-      environment = {
-        DEFAULT_EMAIL = "tm@tlater.net";
-      };
-      extraDockerOptions = [
-        "--volumes-from" "docker-nginx-proxy.service"
-      ];
-    };
+    ## Actual service definitions
+    gitlab = import ./services/gitlab.nix;
 
-    ## GitLab
-    gitlab = {
-      image = "gitlab/gitlab-ce:latest";
-      ports = [
-        "3022:22"
-      ];
-      volumes = [
-        "gitlab-data:/var/opt/gitlab:Z"
-        "gitlab-logs:/var/log/gitlab:Z"
-        "gitlab-config:/etc/gitlab:Z"
-      ];
-      environment = {
-        VIRTUAL_HOST = "gitlab.tlater.net";
-        LETSENCRYPT_HOST = "gitlab.tlater.net";
-        GITLAB_OMNIBUS_CONFIG = builtins.replaceStrings ["\n"] [""] (builtins.readFile ./configs/gitlab.rb);
-      };
-      extraDockerOptions = [
-        "--network=webproxy"
-      ];
     };
   };
 
diff --git a/etc/nixos/configs/gitlab.rb b/etc/nixos/services/configs/gitlab.rb
similarity index 100%
rename from etc/nixos/configs/gitlab.rb
rename to etc/nixos/services/configs/gitlab.rb
diff --git a/etc/nixos/services/gitlab.nix b/etc/nixos/services/gitlab.nix
new file mode 100644
index 0000000..74674a5
--- /dev/null
+++ b/etc/nixos/services/gitlab.nix
@@ -0,0 +1,21 @@
+{ ... }:
+
+{
+  image = "gitlab/gitlab-ce:latest";
+  ports = [
+    "3022:22"
+  ];
+  volumes = [
+    "gitlab-data:/var/opt/gitlab:Z"
+    "gitlab-logs:/var/log/gitlab:Z"
+    "gitlab-config:/etc/gitlab:Z"
+  ];
+  environment = {
+    VIRTUAL_HOST = "gitlab.tlater.net";
+    LETSENCRYPT_HOST = "gitlab.tlater.net";
+    GITLAB_OMNIBUS_CONFIG = builtins.replaceStrings [ "\n" ] [ "" ] (builtins.readFile ./configs/gitlab.rb);
+  };
+  extraDockerOptions = [
+    "--network=webproxy"
+  ];
+}
diff --git a/etc/nixos/services/nginx-proxy-letsencrypt.nix b/etc/nixos/services/nginx-proxy-letsencrypt.nix
new file mode 100644
index 0000000..1d92e70
--- /dev/null
+++ b/etc/nixos/services/nginx-proxy-letsencrypt.nix
@@ -0,0 +1,16 @@
+{ ... }:
+
+{
+  image = "jrcs/letsencrypt-nginx-proxy-companion";
+  volumes = [
+    "/var/run/docker.sock:/var/run/docker.sock:ro"
+    "nginx-certs:/etc/nginx/certs"
+  ];
+  environment = {
+    DEFAULT_EMAIL = "tm@tlater.net";
+  };
+  extraDockerOptions = [
+    "--volumes-from"
+    "docker-nginx-proxy.service"
+  ];
+}
diff --git a/etc/nixos/services/nginx-proxy.nix b/etc/nixos/services/nginx-proxy.nix
new file mode 100644
index 0000000..fe0fd53
--- /dev/null
+++ b/etc/nixos/services/nginx-proxy.nix
@@ -0,0 +1,26 @@
+{ ... }:
+
+{
+  image = "jwilder/nginx-proxy:alpine";
+  ports = [
+    "80:80"
+    "443:443"
+  ];
+  volumes = [
+    # So that we can watch new containers come up
+    "/var/run/docker.sock:/tmp/docker.sock:ro"
+    # So that we can access generated certs
+    "nginx-certs:/etc/nginx/certs:ro"
+    # So that we can write challenge files for letsencrypt auth
+    "nginx-challenges:/usr/share/nginx/html"
+    # So that we can modify config on-the-fly to set up challenge
+    # files
+    "nginx-conf:/etc/nginx/vhost.d"
+  ];
+  environment = {
+    DHPARAM_GENERATION = "false"; # Provided by nginx-proxy-letsencrypt
+  };
+  extraDockerOptions = [
+    "--network=webproxy"
+  ];
+}