Skip to content

Commit 3982faf

Browse files
authored
Merge pull request #16 from mishl-dev/main
feat: load config from env and fix rustic backups bug
2 parents 2d5fec0 + ef48a2c commit 3982faf

File tree

9 files changed

+338
-114
lines changed

9 files changed

+338
-114
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,54 +25,11 @@ jobs:
2525
- name: Download dependencies
2626
run: go mod download
2727

28-
- name: Download rustic binaries
29-
run: make download-rustic
30-
3128
- name: Run tests
3229
run: go test -race ./...
3330

34-
build:
35-
name: Build
36-
runs-on: ubuntu-latest
37-
needs: test
38-
strategy:
39-
matrix:
40-
goos: [linux]
41-
goarch: [amd64, arm64]
42-
steps:
43-
- uses: actions/checkout@v4
44-
45-
- uses: actions/setup-go@v5
46-
with:
47-
go-version-file: go.mod
48-
cache: true
49-
check-latest: true
50-
51-
- name: Download rustic binaries
52-
run: make download-rustic
53-
54-
- name: Build binary
55-
env:
56-
GOOS: ${{ matrix.goos }}
57-
GOARCH: ${{ matrix.goarch }}
58-
CGO_ENABLED: 0
59-
run: |
60-
VERSION=$(git describe --tags --always --dirty)
61-
go build -v -trimpath \
62-
-ldflags="-s -w -X github.com/pyrohost/elytra/src/system.Version=${VERSION}" \
63-
-o dist/elytra_${{ matrix.goos }}_${{ matrix.goarch }} \
64-
./src/cmd/elytra
65-
66-
- name: Upload artifacts
67-
uses: actions/upload-artifact@v4
68-
with:
69-
name: elytra-${{ matrix.goos }}-${{ matrix.goarch }}
70-
path: dist/elytra_${{ matrix.goos }}_${{ matrix.goarch }}
71-
retention-days: 7
72-
compression-level: 0
73-
7431
docker:
75-
name: Docker
32+
name: Docker Build & Push
7633
runs-on: ubuntu-latest
7734
needs: test
7835
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
@@ -83,19 +40,16 @@ jobs:
8340
steps:
8441
- uses: actions/checkout@v4
8542

43+
- uses: docker/setup-qemu-action@v3
44+
8645
- uses: docker/setup-buildx-action@v3
87-
with:
88-
platforms: linux/amd64,linux/arm64
8946

9047
- uses: docker/login-action@v3
9148
with:
9249
registry: ghcr.io
9350
username: ${{ github.actor }}
9451
password: ${{ secrets.GITHUB_TOKEN }}
9552

96-
- name: Download rustic binaries
97-
run: make download-rustic
98-
9953
- name: Extract metadata
10054
id: meta
10155
uses: docker/metadata-action@v5

.github/workflows/release.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ jobs:
2828
- name: Download dependencies
2929
run: go mod download
3030

31-
- name: Download rustic binaries
32-
run: make download-rustic
33-
3431
- name: Build release binaries
3532
env:
3633
CGO_ENABLED: 0
@@ -85,19 +82,16 @@ jobs:
8582
steps:
8683
- uses: actions/checkout@v4
8784

85+
- uses: docker/setup-qemu-action@v3
86+
8887
- uses: docker/setup-buildx-action@v3
89-
with:
90-
platforms: linux/amd64,linux/arm64
9188

9289
- uses: docker/login-action@v3
9390
with:
9491
registry: ghcr.io
9592
username: ${{ github.actor }}
9693
password: ${{ secrets.GITHUB_TOKEN }}
9794

98-
- name: Download rustic binaries
99-
run: make download-rustic
100-
10195
- name: Extract metadata
10296
id: meta
10397
uses: docker/metadata-action@v5

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ debug
5656
*.pprof
5757
*.pdf
5858
pprof.*
59+
data/elytra.db
60+
.secrets
5961

6062
# Nix output files
6163
/result

Dockerfile

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,36 @@
11
# Stage 1 (Build)
2-
FROM golang:1.24-alpine AS builder
2+
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
33

4-
ARG VERSION
5-
ARG RUSTIC_VERSION=0.10.0
4+
ARG TARGETPLATFORM
5+
ARG BUILDPLATFORM
6+
ARG TARGETOS
67
ARG TARGETARCH
7-
RUN apk add --update --no-cache git make mailcap curl bash
8+
ARG VERSION
9+
10+
RUN apk add --update --no-cache git make mailcap
11+
812
WORKDIR /app/
913
COPY go.mod go.sum /app/
10-
RUN go mod download
1114
COPY . /app/
1215

13-
RUN case "$TARGETARCH" in \
14-
amd64) \
15-
ASSET="rustic-v${RUSTIC_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
16-
;; \
17-
arm64) \
18-
ASSET="rustic-v${RUSTIC_VERSION}-aarch64-unknown-linux-musl.tar.gz" \
19-
;; \
20-
*) \
21-
echo "Unsupported architecture: $TARGETARCH"; exit 1 \
22-
;; \
23-
esac && \
24-
mkdir -p /tmp/rustic && \
25-
curl -L https://github.com/rustic-rs/rustic/releases/download/v${RUSTIC_VERSION}/${ASSET} | tar -zx -C /tmp/rustic
26-
27-
28-
RUN CGO_ENABLED=0 go build \
29-
-ldflags="-s -w -X github.com/pyrohost/elytra/src/system.Version=$VERSION" \
30-
-v \
31-
-trimpath \
32-
-o elytra \
33-
./src/cmd/elytra
16+
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
17+
-ldflags="-s -w -X github.com/pyrohost/elytra/src/system.Version=$VERSION" \
18+
-v \
19+
-trimpath \
20+
-o elytra \
21+
./src/cmd/elytra
22+
3423
RUN echo "ID=\"distroless\"" > /etc/os-release
3524

3625
# Stage 2 (Final)
3726
FROM gcr.io/distroless/static:latest
27+
3828
COPY --from=builder /etc/os-release /etc/os-release
3929
COPY --from=builder /etc/mime.types /etc/mime.types
40-
4130
COPY --from=builder /app/elytra /usr/bin/
42-
COPY --from=builder /tmp/rustic/rustic /usr/bin/
31+
COPY --from=ghcr.io/rustic-rs/rustic:v0.10.0 /rustic /usr/local/bin/rustic
4332

4433
ENTRYPOINT ["/usr/bin/elytra"]
4534
CMD ["--config", "/etc/elytra/config.yml"]
4635

47-
EXPOSE 8080 2022
36+
EXPOSE 8080 2022

docker-compose.dev.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
services:
2+
elytra:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
args:
7+
VERSION: dev
8+
RUSTIC_VERSION: v0.10.0
9+
RUSTIC_TARGET: x86_64-unknown-linux-musl
10+
image: elytra:dev
11+
restart: unless-stopped
12+
tty: true
13+
stdin_open: true
14+
ports:
15+
- "8080:8080"
16+
- "2022:2022"
17+
environment:
18+
# Required: Panel connection and token
19+
ELYTRA_PANEL_LOCATION: "https://panel.example.com"
20+
ELYTRA_TOKEN_ID: "local-token-id"
21+
ELYTRA_TOKEN: "local-token-secret"
22+
23+
# Optional overrides / useful defaults
24+
TZ: "UTC"
25+
ELYTRA_DEBUG: "true"
26+
ELYTRA_API_HOST: "0.0.0.0"
27+
ELYTRA_API_PORT: "8080"
28+
ELYTRA_UID: "988"
29+
ELYTRA_GID: "988"
30+
31+
# System path overrides (inside container)
32+
ELYTRA_SYSTEM_ROOT_DIRECTORY: "/var/lib/elytra"
33+
ELYTRA_SYSTEM_DATA: "/var/lib/elytra/volumes"
34+
ELYTRA_SYSTEM_LOG_DIRECTORY: "/var/log/elytra"
35+
36+
# Docker integration (required for managing containers)
37+
ELYTRA_DOCKER_TMPFS_SIZE: "100"
38+
# Disable rustic backups in container mode unless you have the 'rustic' binary available
39+
ELYTRA_SYSTEM_BACKUPS_RUSTIC_LOCAL_ENABLED: "false"
40+
41+
volumes:
42+
- "/var/run/docker.sock:/var/run/docker.sock:ro"
43+
- "/var/lib/docker/containers/:/var/lib/docker/containers/:ro"
44+
- "./data:/var/lib/elytra"
45+
- "./logs:/var/log/elytra"
46+
- "./config.dev.yml:/etc/elytra/config.yml:ro"
47+
48+
networks:
49+
default:
50+
driver: bridge

docker-compose.example.yml

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,41 @@ version: '3.8'
22
services:
33
elytra:
44
image: ghcr.io/pyrohost/elytra:latest
5-
restart: always
6-
networks:
7-
- elytra0
5+
restart: unless-stopped
6+
tty: true
87
ports:
98
- "8080:8080"
109
- "2022:2022"
11-
tty: true
1210
environment:
11+
# Required: Panel connection and token
12+
ELYTRA_PANEL_LOCATION: "https://panel.example.com"
13+
ELYTRA_TOKEN_ID: "panel-token-id"
14+
ELYTRA_TOKEN: "panel-token-value"
15+
16+
# Optional overrides / useful defaults
1317
TZ: "UTC"
14-
ELYTRA_UID: 988
15-
ELYTRA_GID: 988
16-
ELYTRA_USERNAME: pyrodactyl
18+
ELYTRA_DEBUG: "true"
19+
ELYTRA_API_HOST: "0.0.0.0"
20+
ELYTRA_API_PORT: "8080"
21+
ELYTRA_UID: "988"
22+
ELYTRA_GID: "988"
23+
24+
# System path overrides (inside container)
25+
ELYTRA_SYSTEM_ROOT_DIRECTORY: "/var/lib/elytra"
26+
ELYTRA_SYSTEM_DATA: "/var/lib/elytra/volumes"
27+
ELYTRA_SYSTEM_LOG_DIRECTORY: "/var/log/elytra"
28+
29+
# Docker integration (required for managing containers)
30+
ELYTRA_DOCKER_TMPFS_SIZE: "100"
31+
# Disable rustic backups in container mode unless you have the 'rustic' binary available
32+
ELYTRA_SYSTEM_BACKUPS_RUSTIC_LOCAL_ENABLED: "false"
33+
1734
volumes:
18-
- "/var/run/docker.sock:/var/run/docker.sock"
19-
- "/var/lib/docker/containers/:/var/lib/docker/containers/"
20-
- "/etc/elytra/:/etc/elytra/"
21-
- "/var/lib/elytra/:/var/lib/elytra/"
22-
- "/var/log/elytra/:/var/log/elytra/"
23-
- "/tmp/elytra/:/tmp/elytra/"
24-
- "/etc/ssl/certs:/etc/ssl/certs:ro"
25-
# you may need /srv/daemon-data if you are upgrading from an old daemon
26-
#- "/srv/daemon-data/:/srv/daemon-data/"
27-
# Required for ssl if you use let's encrypt. uncomment to use.
28-
#- "/etc/letsencrypt/:/etc/letsencrypt/"
35+
- "/var/run/docker.sock:/var/run/docker.sock:ro"
36+
- "/var/lib/docker/containers/:/var/lib/docker/containers/:ro"
37+
- "./data:/var/lib/elytra"
38+
- "./logs:/var/log/elytra"
39+
2940
networks:
30-
elytra0:
31-
name: elytra0
41+
default:
3242
driver: bridge
33-
ipam:
34-
config:
35-
- subnet: "172.21.0.0/16"
36-
driver_opts:
37-
com.docker.network.bridge.name: elytra0

src/cmd/root.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,35 @@ func initConfig() {
433433
configPath = d
434434
}
435435

436+
// Try to load configuration from the file first. If it doesn't exist, or
437+
// if values required to connect to the Panel are missing, fall back to
438+
// reading from environment variables using the ELYTRA_ prefix.
436439
err := config.FromFile(configPath)
437440
if err != nil {
438441
if errors.Is(err, os.ErrNotExist) {
439-
exitWithConfigurationNotice()
442+
// Attempt to load from environment variables instead of exiting
443+
// immediately. This supports containerized deployments where a
444+
// config file may not be present.
445+
log2.Printf("cmd/root: configuration file not found (%s), attempting to load from environment variables...", configPath)
446+
if err := config.FromEnv(); err != nil {
447+
log2.Fatalf("cmd/root: failed to load configuration from environment: %s", err)
448+
}
449+
} else {
450+
log2.Fatalf("cmd/root: error while reading configuration file: %s", err)
451+
}
452+
}
453+
454+
// Validate we have required configuration; if not, try merging env vars
455+
// into the loaded config (useful when some values are stored in env).
456+
if err := config.ValidateRequired(config.Get()); err != nil {
457+
// Merge environment variables into the existing config and validate again.
458+
log2.Printf("cmd/root: configuration incomplete: %s, attempting to merge environment variables...", err)
459+
if err := config.MergeEnv(config.Get()); err != nil {
460+
log2.Fatalf("cmd/root: failed to merge environment variables: %s", err)
461+
}
462+
if err := config.ValidateRequired(config.Get()); err != nil {
463+
log2.Fatalf("cmd/root: configuration validation failed: %s", err)
440464
}
441-
log2.Fatalf("cmd/root: error while reading configuration file: %s", err)
442465
}
443466
if debug && !config.Get().Debug {
444467
config.SetDebugViaFlag(debug)

src/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import (
2525
"github.com/gbrlsnchs/jwt/v3"
2626
"golang.org/x/sys/unix"
2727
"gopkg.in/yaml.v2"
28-
2928
"github.com/pyrohost/elytra/src/system"
29+
3030
)
3131

3232
const DefaultLocation = "/etc/elytra/config.yml"

0 commit comments

Comments
 (0)