feat: Environment Variables added and more

Reviewed-on: #6
This commit is contained in:
riomoo 2026-01-19 02:41:55 -05:00 committed by moobot
commit 05a1723805
Signed by: moobot
GPG key ID: 1F58B1369E1C199C
10 changed files with 347 additions and 11 deletions

View file

@ -2,11 +2,15 @@
.git .git
.gitignore .gitignore
.gitattributes .gitattributes
bash-scripts scripts-bash
scripts-go
Containerfile Containerfile
Containerfile.build
binaries
README.md README.md
xml-template xml-template
cache cache
etc etc
library library
watch watch
releases

2
.gitignore vendored
View file

@ -7,3 +7,5 @@ cache
library library
etc etc
watch watch
binaries
releases

View file

@ -25,7 +25,7 @@ RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \
-a \ -a \
-ldflags="-s -w -linkmode external -extldflags '-static' -X main.GOMEMLIMIT=512MiB -X runtime.defaultGOGC=50" \ -ldflags="-s -w -linkmode external -extldflags '-static' -X main.GOMEMLIMIT=512MiB -X runtime.defaultGOGC=50" \
-trimpath \ -trimpath \
-o bin/main app/gopherbook/main.go -o bin/main ./app/gopherbook
RUN upx --best --ultra-brute bin/main RUN upx --best --ultra-brute bin/main
RUN chmod +x bin/main RUN chmod +x bin/main

52
Containerfile.build Normal file
View file

@ -0,0 +1,52 @@
# Multi-platform build container for Gopherbook
FROM golang:alpine AS builder
RUN apk add --no-cache \
musl-dev \
gcc \
g++ \
mingw-w64-gcc \
wget \
xz \
git
# Install UPX for binary compression
RUN wget https://github.com/upx/upx/releases/download/v5.0.2/upx-5.0.2-amd64_linux.tar.xz && \
tar -xf upx-5.0.2-amd64_linux.tar.xz && \
mv upx-5.0.2-amd64_linux/upx /usr/local/bin/upx && \
rm -r upx-5.0.2-amd64_linux upx-5.0.2-amd64_linux.tar.xz
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Build Linux binary
RUN echo "Building Linux binary..." && \
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \
-a \
-ldflags="-s -w -linkmode external -extldflags '-static'" \
-trimpath \
-o bin/gopherbook-linux ./app/gopherbook && \
upx --best --ultra-brute bin/gopherbook-linux && \
chmod +x bin/gopherbook-linux
# Build Windows binary
RUN echo "Building Windows binary..." && \
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build \
-a \
-ldflags="-s -w" \
-trimpath \
-o bin/gopherbook-windows.exe ./app/gopherbook && \
upx --best --ultra-brute bin/gopherbook-windows.exe
# Verify binaries were created
RUN ls -lh bin/ && \
echo "Build complete!" && \
echo "Linux binary size: $(du -h bin/gopherbook-linux | cut -f1)" && \
echo "Windows binary size: $(du -h bin/gopherbook-windows.exe | cut -f1)"
# Keep the builder stage as the final stage so we can copy files out
FROM builder

View file

@ -1,5 +1,5 @@
build: build:
go build -o bin/main app/gopherbook/main.go go build -o bin/main ./app/gopherbook
clean: clean:
rm -rf watch etc library cache rm -rf watch etc library cache

View file

@ -78,6 +78,15 @@ Then open http://localhost:12010 in your browser.
./etc/admin.json ← admin settings (registration toggle) ./etc/admin.json ← admin settings (registration toggle)
``` ```
## Environment Variables
Can be used to set where everything is stored with:
```
GOPHERBOOK_LIBRARY=$HOME/.config/gopherbook/library
GOPHERBOOK_CACHE=$HOME/.config/gopherbook/covers
GOPHERBOOK_ETC=$HOME/.config/gopherbook/etc
GOPHERBOOK_WATCH=$HOME/.config/gopherbook/watch
```
## Watch folder for bulk imports ## Watch folder for bulk imports
Gopherbook includes an automatic watch folder system that makes bulk importing comics effortless: Gopherbook includes an automatic watch folder system that makes bulk importing comics effortless:

39
app/gopherbook/config.go Normal file
View file

@ -0,0 +1,39 @@
package main
import (
"os"
"path/filepath"
)
var (
baseLibraryPath string
baseCachePath string
baseEtcPath string
baseWatchPath string
)
func init() {
// Store the base paths (before user-specific paths are added)
baseLibraryPath = libraryPath
baseCachePath = cachePath
baseEtcPath = etcPath
baseWatchPath = watchPath
// Override from environment variables if set
if env := os.Getenv("GOPHERBOOK_LIBRARY"); env != "" {
baseLibraryPath = filepath.Clean(env)
libraryPath = baseLibraryPath
}
if env := os.Getenv("GOPHERBOOK_CACHE"); env != "" {
baseCachePath = filepath.Clean(env)
cachePath = baseCachePath
}
if env := os.Getenv("GOPHERBOOK_ETC"); env != "" {
baseEtcPath = filepath.Clean(env)
etcPath = baseEtcPath
}
if env := os.Getenv("GOPHERBOOK_WATCH"); env != "" {
baseWatchPath = filepath.Clean(env)
watchPath = baseWatchPath
}
}

View file

@ -544,8 +544,8 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
currentUser = req.Username currentUser = req.Username
key := deriveKey(req.Password) key := deriveKey(req.Password)
libraryPath = filepath.Join("./library", currentUser) libraryPath = filepath.Join(baseLibraryPath, currentUser)
cachePath = filepath.Join("./cache/covers", currentUser) cachePath = filepath.Join(baseCachePath, currentUser)
os.MkdirAll(filepath.Join(libraryPath, "Unorganized"), 0755) os.MkdirAll(filepath.Join(libraryPath, "Unorganized"), 0755)
os.MkdirAll(cachePath, 0755) os.MkdirAll(cachePath, 0755)
@ -599,8 +599,8 @@ func handleLogout(w http.ResponseWriter, r *http.Request) {
passwordsMutex.Unlock() passwordsMutex.Unlock()
currentEncryptionKey = nil currentEncryptionKey = nil
currentUser = "" currentUser = ""
libraryPath = "./library" libraryPath = baseLibraryPath
cachePath = "./cache/covers" cachePath = baseCachePath
http.SetCookie(w, &http.Cookie{ http.SetCookie(w, &http.Cookie{
Name: "session", Name: "session",
@ -2697,9 +2697,16 @@ func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
next(w, r) next(w, r)
} }
} }
func getUsersPath() string {
return filepath.Join(etcPath, "users.json")
}
func getAdminPath() string {
return filepath.Join(etcPath, "admin.json")
}
func loadUsers() { func loadUsers() {
data, err := os.ReadFile("etc/users.json") data, err := os.ReadFile(getUsersPath())
if err != nil { if err != nil {
return return
} }
@ -2707,7 +2714,7 @@ func loadUsers() {
log.Printf("Error unmarshaling users: %v", err) log.Printf("Error unmarshaling users: %v", err)
} }
adminData, err := os.ReadFile("etc/admin.json") adminData, err := os.ReadFile(getAdminPath())
if err == nil && len(adminData) > 0 { if err == nil && len(adminData) > 0 {
var adminConfig struct{ RegistrationEnabled bool } var adminConfig struct{ RegistrationEnabled bool }
if err := json.Unmarshal(adminData, &adminConfig); err == nil { if err := json.Unmarshal(adminData, &adminConfig); err == nil {
@ -2718,13 +2725,13 @@ func loadUsers() {
func saveUsers() { func saveUsers() {
data, _ := json.MarshalIndent(users, "", " ") data, _ := json.MarshalIndent(users, "", " ")
os.WriteFile("etc/users.json", data, 0644) os.WriteFile(getUsersPath(), data, 0644)
} }
func saveAdminConfig() { func saveAdminConfig() {
config := struct{ RegistrationEnabled bool }{RegistrationEnabled: registrationEnabled} config := struct{ RegistrationEnabled bool }{RegistrationEnabled: registrationEnabled}
data, _ := json.MarshalIndent(config, "", " ") data, _ := json.MarshalIndent(config, "", " ")
os.WriteFile("etc/admin.json", data, 0644) os.WriteFile(getAdminPath(), data, 0644)
} }
func loadTags() { func loadTags() {

62
scripts-bash/build-release.sh Executable file
View file

@ -0,0 +1,62 @@
#!/bin/bash
set -e
IMAGE_NAME="localhost/gopherbook-builder:latest"
CONTAINER_NAME="gopherbook-builder-tmp"
OUTPUT_DIR="./binaries"
echo "=== Building cross-compilation container ==="
podman build --force-rm -t "$IMAGE_NAME" -f Containerfile.build .
if [ $? -ne 0 ]; then
echo "Image build failed. Exiting."
exit 1
fi
echo ""
echo "=== Creating temporary container ==="
podman create --name "$CONTAINER_NAME" "$IMAGE_NAME"
echo ""
echo "=== Creating output directory ==="
mkdir -p "$OUTPUT_DIR"
rm -f "$OUTPUT_DIR"/*
echo ""
echo "=== Extracting Linux binary ==="
podman cp "$CONTAINER_NAME:/app/bin/gopherbook-linux" "$OUTPUT_DIR/gopherbook-linux"
chmod +x "$OUTPUT_DIR/gopherbook-linux"
echo ""
echo "=== Extracting Windows binary ==="
podman cp "$CONTAINER_NAME:/app/bin/gopherbook-windows.exe" "$OUTPUT_DIR/gopherbook-windows.exe"
chmod +x "$OUTPUT_DIR/gopherbook-windows.exe"
echo ""
echo "=== Cleaning up temporary container ==="
podman rm "$CONTAINER_NAME"
echo ""
echo "=== Build complete! ==="
echo "Binaries are in: $OUTPUT_DIR/"
ls -lh "$OUTPUT_DIR/"
echo ""
echo "=== Binary sizes ==="
du -h "$OUTPUT_DIR"/*
echo ""
echo "=== Cleaning up builder image ==="
podman rmi "$IMAGE_NAME"
echo ""
echo "✓ Done! Your binaries are ready:"
echo " • Linux: $OUTPUT_DIR/gopherbook-linux"
echo " • Windows: $OUTPUT_DIR/gopherbook-windows.exe"
echo ""
echo "To run the Linux binary:"
echo " $OUTPUT_DIR/gopherbook-linux"
echo ""
echo "To test the Windows binary (requires wine):"
echo " wine $OUTPUT_DIR/gopherbook-windows.exe"

161
scripts-bash/package-release.sh Executable file
View file

@ -0,0 +1,161 @@
#!/bin/bash
set -e
VERSION="${1:-v1.1.000}"
RELEASE_DIR="./releases"
BINARIES_DIR="./binaries"
echo "=== Packaging Gopherbook $VERSION ==="
echo ""
# Create release directory
mkdir -p "$RELEASE_DIR"
# Clean old releases for this version
rm -f "$RELEASE_DIR"/gopherbook-$VERSION-*
# Check if binaries exist
if [ ! -f "$BINARIES_DIR/gopherbook-linux" ] || [ ! -f "$BINARIES_DIR/gopherbook-windows.exe" ]; then
echo "Error: Binaries not found. Run ./build-and-extract.sh first."
exit 1
fi
echo "=== Creating README.txt ==="
cat > /tmp/README.txt << 'EOF'
Gopherbook - Comic Book Reader (CBZ/CBT)
=========================================
Quick Start:
------------
1. Run the gopherbook executable
2. Open your browser to http://localhost:8080
3. Register a new user account
4. Upload your CBZ/CBT comic files
Features:
---------
• Supports CBZ (ZIP) and CBT (TAR) formats
• Password-protected archives
• Tag management and filtering
• Bookmark pages
• Auto-organize by artist and story arc
• Watch folder for automatic imports
• Multi-user support with admin controls
Watch Folder:
-------------
Place CBZ/CBT files in the ./watch/<username>/ directory
and they will be automatically imported to your library.
Directory Structure:
--------------------
./library/ - Your comic library (per user)
./cache/ - Cover image cache
./etc/ - User data and settings
./watch/ - Watch folders for auto-import
Default Port: 8080
For more information, visit:
https://github.com/riomoo/gopherbook
https://codeberg.org/riomoo/gofudge
https://gitgud.io/riomoo/gopherbook
EOF
echo "=== Creating Linux package ==="
LINUX_DIR="/tmp/gopherbook-linux"
rm -rf "$LINUX_DIR"
mkdir -p "$LINUX_DIR"
# Copy Linux binary
cp "$BINARIES_DIR/gopherbook-linux" "$LINUX_DIR/gopherbook"
chmod +x "$LINUX_DIR/gopherbook"
# Copy documentation
cp /tmp/README.txt "$LINUX_DIR/"
# Create run script
cat > "$LINUX_DIR/run.sh" << 'EOF'
#!/bin/bash
echo "Starting Gopherbook..."
echo "Open your browser to: http://localhost:8080"
echo "Press Ctrl+C to stop"
echo ""
./gopherbook
EOF
chmod +x "$LINUX_DIR/run.sh"
# Package Linux
cd /tmp
tar -czf "$LINUX_DIR.tar.gz" gopherbook-linux/
cd - > /dev/null
mv "/tmp/gopherbook-linux.tar.gz" "$RELEASE_DIR/gopherbook-$VERSION-linux-amd64.tar.gz"
rm -rf "$LINUX_DIR"
echo "✓ Linux package created"
echo ""
echo "=== Creating Windows package ==="
WINDOWS_DIR="/tmp/gopherbook-windows"
rm -rf "$WINDOWS_DIR"
mkdir -p "$WINDOWS_DIR"
# Copy Windows binary
cp "$BINARIES_DIR/gopherbook-windows.exe" "$WINDOWS_DIR/gopherbook.exe"
# Copy documentation (Windows line endings)
unix2dos < /tmp/README.txt > "$WINDOWS_DIR/README.txt" 2>/dev/null || cp /tmp/README.txt "$WINDOWS_DIR/README.txt"
# Create batch file
cat > "$WINDOWS_DIR/run.bat" << 'EOF'
@echo off
echo Starting Gopherbook...
echo Open your browser to: http://localhost:8080
echo Press Ctrl+C to stop
echo.
gopherbook.exe
pause
EOF
# Create PowerShell script
cat > "$WINDOWS_DIR/run.ps1" << 'EOF'
Write-Host "Starting Gopherbook..." -ForegroundColor Green
Write-Host "Open your browser to: http://localhost:8080" -ForegroundColor Cyan
Write-Host "Press Ctrl+C to stop" -ForegroundColor Yellow
Write-Host ""
.\gopherbook.exe
EOF
# Package Windows
cd /tmp
zip -q -r "$WINDOWS_DIR.zip" gopherbook-windows/
cd - > /dev/null
mv "/tmp/gopherbook-windows.zip" "$RELEASE_DIR/gopherbook-$VERSION-windows-amd64.zip"
rm -rf "$WINDOWS_DIR"
echo "✓ Windows package created"
echo ""
echo "=== Creating checksums ==="
cd "$RELEASE_DIR"
sha256sum gopherbook-$VERSION-*.tar.gz gopherbook-$VERSION-*.zip > gopherbook-$VERSION-checksums.txt
cd - > /dev/null
echo "✓ Checksums created"
echo ""
echo "=== Release packages ready! ==="
echo ""
ls -lh "$RELEASE_DIR"/gopherbook-$VERSION-*
echo ""
echo "Release files:"
echo "$RELEASE_DIR/gopherbook-$VERSION-linux-amd64.tar.gz"
echo "$RELEASE_DIR/gopherbook-$VERSION-windows-amd64.zip"
echo "$RELEASE_DIR/gopherbook-$VERSION-checksums.txt"
echo ""
echo "Upload these files to GitHub Releases!"
# Cleanup
rm -f /tmp/README.txt