Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# =============================================================================
# MAIN CONFIGURATION
# FRONTEND CONFIGURATION
# =============================================================================
BASE_URL=http://localhost:8080 # Public URL (backend + frontend use this)
#CORS_ORIGIN=http://localhost:3000 # Optional: Only set if frontend is on different domain
BASE_URL=http://localhost:3000
API_URL=http://localhost:8080/api

# =============================================================================
# SERVER
# BACKEND CONFIGURATION
# =============================================================================
PORT=8080
DB_PATH=./data/formera.db
JWT_SECRET=your-secure-secret-here # CHANGE IN PRODUCTION!
#CORS_ORIGIN=http://localhost:3000 # Optional: Only set if frontend is on different domain

# =============================================================================
# STORAGE
Expand Down Expand Up @@ -43,4 +43,4 @@ CLEANUP_DRY_RUN=false
# =============================================================================
# SEO (optional)
# =============================================================================
NUXT_PUBLIC_INDEXABLE=true # Set to "false" to disallow search engine indexing
PUBLIC_INDEXABLE=true # Set to "false" to disallow search engine indexing
46 changes: 0 additions & 46 deletions .github/workflows/lint.yml

This file was deleted.

60 changes: 54 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build and Push Docker Image
name: Build and Push Docker Images

on:
push:
Expand Down Expand Up @@ -27,7 +27,7 @@ jobs:
run: go test -v -race ./...
working-directory: backend

build-and-push:
build-backend:
needs: test
runs-on: ubuntu-latest
permissions:
Expand All @@ -51,21 +51,69 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels)
- name: Extract metadata (tags, labels) for Backend
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
- name: Build and push Backend Docker image
uses: docker/build-push-action@v5
with:
context: .
context: ./backend
file: ./backend/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

build-frontend:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Frontend
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Frontend Docker image
uses: docker/build-push-action@v5
with:
context: ./frontend
file: ./frontend/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
Expand Down
60 changes: 0 additions & 60 deletions Dockerfile

This file was deleted.

110 changes: 82 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,32 @@ Self-hosted form builder. Privacy-friendly alternative to Google Forms.

## Quick Start

### Docker

```bash
docker run -d \
-p 8080:80 \
-v formera-data:/app/data \
-e BASE_URL=https://forms.example.com \
-e JWT_SECRET=your-secure-secret-here \
ghcr.io/formeraapp/formera:latest
```

### Docker Compose
### Docker Compose (Recommended)

```yaml
services:
formera:
image: ghcr.io/formeraapp/formera:latest
container_name: formera
backend:
image: ghcr.io/formeraapp/formera-backend:latest
container_name: formera-backend
restart: unless-stopped
environment:
- BASE_URL=https://forms.example.com
- JWT_SECRET=your-secure-secret-here
# - CORS_ORIGIN=https://other-domain.com # Optional: only if frontend is on different domain
ports:
- "8080:8080"
volumes:
- formera-data:/app/data
environment:
- JWT_SECRET=your-secure-secret-here # CHANGE IN PRODUCTION!

frontend:
image: ghcr.io/formeraapp/formera-frontend:latest
container_name: formera-frontend
restart: unless-stopped
ports:
- "8080:80"
- "3000:3000"
environment:
- NUXT_PUBLIC_BASE_URL=http://localhost:3000
- NUXT_PUBLIC_API_URL=http://localhost:8080/api
depends_on:
- backend

volumes:
formera-data:
Expand All @@ -62,34 +61,55 @@ volumes:
docker compose up -d
```

Access at `http://localhost`. Setup wizard appears on first start.
Access at `http://localhost:3000`. Setup wizard appears on first start.

### Docker (Separate Containers)

**Backend:**
```bash
docker run -d \
-p 8080:8080 \
-v formera-data:/app/data \
-e JWT_SECRET=your-secure-secret-here \
ghcr.io/formeraapp/formera-backend:latest
```

**Frontend:**
```bash
docker run -d \
-p 3000:3000 \
-e NUXT_PUBLIC_BASE_URL=http://localhost:3000 \
-e NUXT_PUBLIC_API_URL=http://localhost:8080/api \
ghcr.io/formeraapp/formera-frontend:latest
```

### Development

```bash
# Backend
cd backend && go run ./cmd/server
cd backend && go run ./cmd/server serve

# Frontend
cd frontend && yarn install && yarn dev
```

## Configuration

### Main
### Frontend

| Variable | Description | Default |
|----------|-------------|---------|
| `BASE_URL` | Public URL of the application | `http://localhost:8080` |
| `CORS_ORIGIN` | Allowed origin (optional, defaults to BASE_URL) | - |
| `JWT_SECRET` | JWT signing key (change in production!) | - |
| `NUXT_PUBLIC_BASE_URL` | Public URL of the frontend | `http://localhost:3000` |
| `NUXT_PUBLIC_API_URL` | Backend API URL | `http://localhost:8080/api` |

### Server
### Backend

| Variable | Description | Default |
|----------|-------------|---------|
| `PORT` | Backend port | `8080` |
| `DB_PATH` | SQLite database path | `./data/formera.db` |
| `JWT_SECRET` | JWT signing key (change in production!) | - |
| `CORS_ORIGIN` | Allowed origin (optional) | - |

### Storage

Expand Down Expand Up @@ -131,7 +151,41 @@ cd frontend && yarn install && yarn dev

| Variable | Description | Default |
|----------|-------------|---------|
| `NUXT_PUBLIC_INDEXABLE` | Allow search engine indexing | `true` |
| `PUBLIC_INDEXABLE` | Allow search engine indexing | `true` |

## Production Setup with Reverse Proxy

Example with Traefik:

```yaml
services:
backend:
image: ghcr.io/formeraapp/formera-backend:latest
restart: unless-stopped
volumes:
- formera-data:/app/data
environment:
- JWT_SECRET=${JWT_SECRET}
- CORS_ORIGIN=https://forms.example.com
labels:
- "traefik.enable=true"
- "traefik.http.routers.formera-api.rule=Host(`forms.example.com`) && PathPrefix(`/api`)"
- "traefik.http.services.formera-api.loadbalancer.server.port=8080"

frontend:
image: ghcr.io/formeraapp/formera-frontend:latest
restart: unless-stopped
environment:
- NUXT_PUBLIC_BASE_URL=https://forms.example.com
- NUXT_PUBLIC_API_URL=https://forms.example.com/api
labels:
- "traefik.enable=true"
- "traefik.http.routers.formera.rule=Host(`forms.example.com`)"
- "traefik.http.services.formera.loadbalancer.server.port=3000"

volumes:
formera-data:
```

## Testing

Expand Down
Loading
Loading