feat(deploy): add Caddy config used in prod
+ 146
- 26
@@ -0,0 +1,15 @@
+gitfoss.dev {
+  tls {
+    issuer zerossl [stripped]
+  }
+  reverse_proxy gitfoss_web:1337 {
+    header_up X-Real-IP {remote}
+    header_up X-Forwarded-For {remote}
+    header_up X-Forwarded-Proto {remote}
+    header_up Host {host}^
+  }
+}
+
+www.gitfoss.dev, gitfoss.sk, gitfoss.tech {
+  redir https://gitfoss.dev{uri} 301
+}

data/ssh_command_node
@@ -1,5 +1,6 @@
 #!/usr/bin/node
 
+const http = require("http");
 const fs = require("fs");
 
 async function main(args, sshOriginalCommand) {

...
@@ -15,7 +16,7 @@ async function main(args, sshOriginalCommand) {
 
   const authorizedKeysBuffer = fs.readFileSync(
     "/home/git/.ssh/authorized_keys",
-    { encoding: "utf8" }
+    { encoding: "utf8" },
   );
 
   const authKeys = authorizedKeysBuffer

...
@@ -24,14 +25,23 @@ async function main(args, sshOriginalCommand) {
       line.startsWith("#")
         ? { type: "comment", text: line }
         : line.trim() !== ""
-        ? { type: "key", text: line.trim() }
-        : null
+          ? { type: "key", text: line.trim() }
+          : null,
     )
     .filter((x) => x != null && x.type === "key");
 
-  const pk = authKeys.find((key) =>
-    key.text.includes(`command="ssh_command ${username}"`)
-  )?.text;
+  console.log("authkeys:", authKeys);
+  console.log("username", username);
+
+  let pk = authKeys.find(
+    (key) =>
+      key.text.includes(`command="ssh_command ${username}"`) ||
+      key.text.includes(`command="/usr/bin/ssh_command ${username}"`),
+  );
+
+  if (pk) {
+    pk = pk.text;
+  }
 
   const sshRsaIndex = pk.indexOf("ssh-rsa");
   const publicKey = pk.substring(sshRsaIndex);

...
@@ -43,37 +53,78 @@ async function main(args, sshOriginalCommand) {
   fs.appendFileSync(
     "/home/git/ssh_commands.log",
     `username: ${username}\npublicKey: ${publicKey}\ncommand: ${command}\nrepoSlug: ${repoSlug}\n-----------\n`,
-    { encoding: "utf8" }
+    { encoding: "utf8" },
   );
 
-  const res = await fetch(`http://localhost:1337/_ssh/auth`, {
+  const data = JSON.stringify({
+    command,
+    repoSlug,
+    username,
+    publicKey,
+  });
+
+  const options = {
+    hostname: "localhost",
+    port: 1337,
+    path: "/_ssh/auth",
     method: "POST",
-    body: JSON.stringify({
-      command,
-      repoSlug,
-      username,
-      publicKey,
-    }),
+    headers: {
+      "Content-Type": "application/json",
+      "Content-Length": Buffer.byteLength(data),
+    },
+  };
+
+  let json = {};
+
+  const req = http.request(options, (res) => {
+    let chunks = [];
+
+    res.on("data", (chunk) => {
+      chunks.push(chunk);
+    });
+
+    res.on("end", () => {
+      const responseBody = Buffer.concat(chunks).toString();
+
+      if (res.statusCode >= 400) {
+        // Log error details
+        fs.appendFileSync(
+          "/home/git/ssh_commands.log",
+          `${res.statusCode}: ${res.statusMessage} - ${responseBody}\n-----------\n`,
+          { encoding: "utf8" },
+        );
+        process.exit(128);
+      } else {
+        // Parse JSON response
+        try {
+          json = JSON.parse(responseBody);
+          // Do something with json if needed
+        } catch (e) {
+          // handle JSON parse error if necessary
+        }
+      }
+    });
   });
 
-  if (res.ok === false) {
-    const text = await res.text();
+  req.on("error", (e) => {
+    // handle request error
     fs.appendFileSync(
       "/home/git/ssh_commands.log",
-      `${res.status}: ${res.statusText} - ${text}\n-----------\n`,
-      { encoding: "utf8" }
+      `Request error: ${e.message}\n-----------\n`,
+      { encoding: "utf8" },
     );
-
     process.exit(128);
-  }
+  });
 
-  const json = await res.json();
+  // Write data to request body
+  req.write(data);
+  req.end();
 
-  fs.appendFileSync(
-    "/home/git/ssh_commands.log",
-    `${res.status}: ${res.statusText} - ${JSON.stringify(json)}\n-----------\n`,
-    { encoding: "utf8" }
-  );
+  // fs.appendFileSync(
+  //   "/home/git/ssh_commands.log",
+  //   `${res.status}: ${res.statusText} - ${JSON.stringify(json)}\n-----------\n`,
+  //   { encoding: "utf8" },
+  // );
 
   if (json.success === false) {
     process.exit(128);

new file
docker-compose.caddy.yml
@@ -0,0 +1,54 @@
+version: "3.3"
+services:
+  caddy:
+    restart: always
+    image: "caddy:latest"
+    container_name: gitfoss_caddy
+    networks:
+      - reverse-proxy-public
+    ports:
+      - "80:80"
+      - "443:443"
+    volumes:
+      - /var/run/docker.sock:/var/run/docker.sock:ro
+      - ./Caddyfile:/etc/caddy/Caddyfile
+      - ./data/caddy/data:/data
+      - ./data/caddy/config:/config
+  db:
+    restart: always
+    container_name: gitfoss_db
+    image: "postgres:14"
+    environment:
+      - POSTGRES_PASSWORD=change_me_password
+      - POSTGRES_DB=gitfoss
+    networks:
+      - internal
+    volumes:
+      - ./data/postgres_data:/var/lib/postgresql/data
+  web:
+    restart: always
+    image: "gitfoss_web:latest"
+    container_name: gitfoss_web
+    depends_on:
+      - db
+    environment:
+      - COOKIE_NAME=gitfoss_ssid
+      - COOKIE_SECRET=change_me_cookie_secret
+      - DATABASE_URL=postgresql://postgres:change_me_password@gitfoss_db/gitfoss?sslmode=disable&connection_limit=3
+      - DEPLOYMENT_DOMAIN=${DOMAIN:-gitfoss.dev}
+      - DEPLOYMENT_SCHEME=https
+      - GIT_REPOSITORIES_ROOT=/var/lib/gitfoss/repos
+      - PORT=1337
+    ports:
+      #- "1337:1337"
+      #- "2223:22"
+    networks:
+      - internal
+      - reverse-proxy-public
+    volumes:
+      - ./data/gitfoss_repos:/var/lib/gitfoss/repos
+      #- /home/git/repos:/var/lib/gitfoss/repos
+
+networks:
+  internal:
+  reverse-proxy-public: