diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..be4cce4 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +VAULT_NAME=test-campaign \ No newline at end of file diff --git a/README.md b/README.md index dbb22a0..5eb9670 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ -# Simple Publisher +# DND Vault Template -Dead simple self hosted Obsidian publisher. +Template for publishing DND campaign vaults -## How does it work +## Instructions -You have your vault synced through git to some remote repository. +- Create a deploymenty machine where you should have ssh access +- Create a repository with your vault + - All the notes should fall under `content/` inside your vault + - Place `gitea/workflows/deploy.yml` under `.gitea/workflows/deploy.yml`. + - Change env variables +- When you push on the vault repository, the workflow file will clone and setup this nuxt app with the contents of the vault and publish it. -When you push to the vault repository this triggers a webhook to a repo that you have with this cloned repo, it does something magic and then it deploys a website to wherever you like. +## Env variables -Also you can have multiple vaults! +For gitea, you should set: +- `DEPLOY_HOST`: Host to deploy the vault +- `DEPLOY_KEY`: SSH id_ed25519 for accessing the host +- `REGISTRY_USER`: User for the docker registry +- `REGISTRY_PASSWORD`: Password to the docker registry -Valuts -> Simple Publisher -> Multiple deployment sites +Inside deploy.yml: +- `TEMPLATE_REPO_URL`: Should point to THIS repo +- `TARGET_SUBFOLDER`: Where to clone content of the vault. No need to change it from `template/content` +- `VAULT_NAME`: Your vault name. Used for the name of the generated docker images \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..eb01460 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.9" + +services: + nginx: + image: nginx:latest + ports: + - "3000:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + depends_on: + - frontend + restart: always + + frontend: + image: git.aranroig.com/syndria98/vault-${VAULT_NAME}:latest + restart: always \ No newline at end of file diff --git a/gitea/workflows/deploy.yml b/gitea/workflows/deploy.yml index 00b2225..6c32cab 100644 --- a/gitea/workflows/deploy.yml +++ b/gitea/workflows/deploy.yml @@ -13,31 +13,65 @@ jobs: # URL of the repository to clone TEMPLATE_REPO_URL: https://git.aranroig.com/Syndria98/dnd-vault-template.git # Folder name inside the target repo where this repo's contents will be placed - TARGET_SUBFOLDER: my-repo-contents + TARGET_SUBFOLDER: template/content + VAULT_NAME: test-campaign steps: - - name: Checkout current repository + - name: Checkout uses: actions/checkout@v3 with: - path: current-repo + path: current + + - name: Install SSH client + run: | + apt-get update -y && apt-get install -y openssh-client + + - name: Setup SSH inside container + run: | + mkdir -p ~/.ssh + echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + + # Add the container host to known_hosts + ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts + + - name: Log in to registry + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.aranroig.com -u "${{ secrets.REGISTRY_USER }}" --password-stdin - name: Clone target repository run: | - git clone "$TEMPLATE_REPO_URL" target-repo + git clone "$TEMPLATE_REPO_URL" target - name: Copy current repo contents into target subfolder run: | - mkdir -p target-repo/$TARGET_SUBFOLDER + rm -R target/$TARGET_SUBFOLDER + mkdir -p target/$TARGET_SUBFOLDER # Exclude the .git directory from the copy - rsync -av --exclude='.git' current-repo/ target-repo/$TARGET_SUBFOLDER/ + rsync -av --exclude={.git,.obsidian,.gitea} current/content/ target/$TARGET_SUBFOLDER/ - - name: List result (dry run verification) + - name: Build frontend run: | - echo "=== Contents of target repo after copy ===" - find target-repo -not -path '*/.git/*' | sort + docker build -t git.aranroig.com/${{ secrets.REGISTRY_USER }}/vault-$VAULT_NAME:latest ./target/template + docker push git.aranroig.com/${{ secrets.REGISTRY_USER }}/vault-$VAULT_NAME:latest - - name: Upload result as artifact - uses: actions/upload-artifact@v3 - with: - name: target-repo-with-contents - path: target-repo/ \ No newline at end of file + - name: Generate docker compose .env + run: | + cat > ./target/.env << EOF + VAULT_NAME=$VAULT_NAME + EOF + + - name: Copy files + run: | + scp ./target/docker-compose.yml deploy@${{ secrets.DEPLOY_HOST}}:/var/www/app/ + scp ./target/nginx.conf deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/nginx.conf + scp ./target/.env deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/.env + + - name: Deploy + run: | + ssh deploy@${{ secrets.DEPLOY_HOST }} << 'EOF' + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.aranroig.com -u "${{ secrets.REGISTRY_USER }}" --password-stdin + cd /var/www/app/ + docker-compose pull + docker-compose up -d + EOF diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..b20b7df --- /dev/null +++ b/nginx.conf @@ -0,0 +1,24 @@ +events {} + +http { + server { + listen 80; + server_name _; + + # Can we add small backend in the future? + + # Normal requests + location / { + proxy_pass http://frontend:3000; + + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + } +} diff --git a/template/.dockerignore b/template/.dockerignore new file mode 100644 index 0000000..3974245 --- /dev/null +++ b/template/.dockerignore @@ -0,0 +1,7 @@ +node_modules +.git +.gitignore +Dockerfile +.dockerignore +npm-debug.log +.env \ No newline at end of file diff --git a/template/Dockerfile b/template/Dockerfile new file mode 100644 index 0000000..f6e45ab --- /dev/null +++ b/template/Dockerfile @@ -0,0 +1,32 @@ +# ---------- Build Stage ---------- +FROM node:20-alpine AS builder + +WORKDIR /app + +RUN apk add --no-cache python3 make g++ git + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install + +ARG CACHEBUST=1 +COPY . . + +# Build the Nuxt app +RUN npm run build + +# ---------- Production Stage ---------- +FROM node:20-alpine + +WORKDIR /app + +# Copy built output +COPY --from=builder /app/.output ./.output + +# Expose Nuxt port +EXPOSE 3000 + +# Start Nuxt production server +CMD ["node", ".output/server/index.mjs"]