From c734b445a8887336ee3ddcd95748c2e6526f4912 Mon Sep 17 00:00:00 2001 From: Yuri Tatishchev Date: Tue, 24 Dec 2024 03:23:58 -0800 Subject: [PATCH] docker build setup --- .dockerignore | 33 ++++++++++++++++++++ .env.example | 2 ++ Dockerfile | 45 +++++++++++++++++++++++++++ README.md | 2 ++ bun.lockb | Bin 168043 -> 168043 bytes entrypoint.sh | 8 +++++ package.json | 6 ++-- src/hooks.server.ts | 6 +++- src/lib/server/opnsense/index.ts | 51 +++++++++++++++++-------------- 9 files changed, 126 insertions(+), 27 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0fb12e8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,33 @@ +node_modules + +# Output +.output +.vercel +/.svelte-kit +/build + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* + +# SQLite +*.db + +# Git +/.git + +# IntelliJ +/.idea + +# Bruno (API Docs) +/bruno diff --git a/.env.example b/.env.example index c01debe..bdcb8f5 100644 --- a/.env.example +++ b/.env.example @@ -16,3 +16,5 @@ IP_MAX_INDEX=100 VPN_ENDPOINT=vpn.lab.cazzzer.com:51820 VPN_DNS=10.18.11.1,fd00:10:18:11::1 MAX_CLIENTS_PER_USER=20 + +ORIGIN=http://localhost:5173 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4cd40ea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# use the official Bun image +# see all versions at https://hub.docker.com/r/oven/bun/tags +FROM oven/bun:1-alpine AS base +WORKDIR /app +COPY package.json bun.lockb /app/ + +# install dependencies into temp directory +# this will cache them and speed up future builds +FROM base AS install +RUN mkdir -p /temp/dev +COPY package.json bun.lockb /temp/dev/ +RUN cd /temp/dev && bun install --frozen-lockfile + +# install with --production (exclude devDependencies) +RUN mkdir -p /temp/prod +COPY package.json bun.lockb /temp/prod/ +RUN cd /temp/prod && bun install --frozen-lockfile --production + +# copy node_modules from temp directory +# then copy all (non-ignored) project files into the image +FROM base AS builder +COPY --from=install /temp/dev/node_modules /app/node_modules +COPY . /app +RUN bun run build + +FROM base +# Metadata +LABEL org.opencontainers.image.title="VPGen" +LABEL org.opencontainers.image.description="A VPN config generator built with SvelteKit." +LABEL org.opencontainers.image.url="https://gitea.cazzzer.com/CaZzzer/vpgen" +LABEL org.opencontainers.image.source="https://gitea.cazzzer.com/CaZzzer/vpgen" +LABEL org.opencontainers.image.version="0.1" + +COPY ./entrypoint.sh /entrypoint.sh +COPY --from=install /temp/prod/node_modules /app/node_modules +COPY --from=builder /app/build /app/build +COPY --from=builder /app/drizzle /app/drizzle +COPY --from=builder /app/drizzle.config.ts /app/ + +EXPOSE 3000 + +# entrypoint for drizzle migrations +ENTRYPOINT ["sh", "/entrypoint.sh"] + +CMD ["bun", "./build"] diff --git a/README.md b/README.md index b5b2950..0d62b61 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,5 @@ npm run build You can preview the production build with `npm run preview`. > To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. + +When deploying, set `ORIGIN` to the URL of your site to prevent cross-site request errors. diff --git a/bun.lockb b/bun.lockb index 476dd0b8467984ee4a7a1ba15a2ff76d12c09ae1..6c477e635d46d9b02b8ae7731b932dec6845f507 100755 GIT binary patch delta 26571 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 J@$!Hg{|oKnBtZZG delta 26660 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 { const sessionId = event.cookies.get(auth.sessionCookieName); diff --git a/src/lib/server/opnsense/index.ts b/src/lib/server/opnsense/index.ts index f2a3ee4..6f4618b 100644 --- a/src/lib/server/opnsense/index.ts +++ b/src/lib/server/opnsense/index.ts @@ -12,33 +12,38 @@ export const opnsenseIfname = env.OPNSENSE_WG_IFNAME; // unset secret for security if (!dev) env.OPNSENSE_API_SECRET = ''; +export let serverUuid: string, serverPublicKey: string; + +export async function fetchOpnsenseServer() { // this might be pretty bad if the server is down and in a bunch of other cases // TODO: write a retry loop later -const resServers = await fetch(`${opnsenseUrl}/api/wireguard/client/list_servers`, { - method: 'GET', - headers: { - Authorization: opnsenseAuth, - Accept: 'application/json', - }, -}); -assert(resServers.ok, 'Failed to fetch OPNsense WireGuard servers'); -const servers = (await resServers.json()) as OpnsenseWgServers; -assert.equal(servers.status, 'ok', 'Failed to fetch OPNsense WireGuard servers'); -export const serverUuid = servers.rows.find((server) => server.name === opnsenseIfname)?.uuid; -assert(serverUuid, 'Failed to find server UUID for OPNsense WireGuard server'); -console.log('OPNsense WireGuard server UUID:', serverUuid); - -const resServerInfo = await fetch( - `${opnsenseUrl}/api/wireguard/client/get_server_info/${serverUuid}`, - { + const resServers = await fetch(`${opnsenseUrl}/api/wireguard/client/list_servers`, { method: 'GET', headers: { Authorization: opnsenseAuth, Accept: 'application/json', }, - }, -); -assert(resServerInfo.ok, 'Failed to fetch OPNsense WireGuard server info'); -const serverInfo = await resServerInfo.json(); -assert.equal(serverInfo.status, 'ok', 'Failed to fetch OPNsense WireGuard server info'); -export const serverPublicKey = serverInfo['pubkey']; + }); + assert(resServers.ok, 'Failed to fetch OPNsense WireGuard servers'); + const servers = (await resServers.json()) as OpnsenseWgServers; + assert.equal(servers.status, 'ok', 'Failed to fetch OPNsense WireGuard servers'); + const uuid = servers.rows.find((server) => server.name === opnsenseIfname)?.uuid; + assert(uuid, 'Failed to find server UUID for OPNsense WireGuard server'); + serverUuid = uuid; + console.log('OPNsense WireGuard server UUID:', serverUuid); + + const resServerInfo = await fetch( + `${opnsenseUrl}/api/wireguard/client/get_server_info/${serverUuid}`, + { + method: 'GET', + headers: { + Authorization: opnsenseAuth, + Accept: 'application/json', + }, + }, + ); + assert(resServerInfo.ok, 'Failed to fetch OPNsense WireGuard server info'); + const serverInfo = await resServerInfo.json(); + assert.equal(serverInfo.status, 'ok', 'Failed to fetch OPNsense WireGuard server info'); + serverPublicKey = serverInfo['pubkey']; +}