🦈🏠🐜 Initial Commit 🐜🦈🏠

This commit is contained in:
casjay
2026-06-26 14:10:54 -04:00
commit 134db61c18
21 changed files with 5486 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
# Files to ignore
# Tell docker to ignore .gitkeep
.gitkeep
# Tell docker to ignore .gitignore
.gitignore
# Tell docker to ignore node_modules/**
node_modules/**
# Tell docker to ignore .node_modules/**
.node_modules/**
# Tell docker to ignore **/.gitkeep
**/.gitkeep
# Tell docker to ignore **/.gitignore
**/.gitignore
# Tell docker to ignore **/node_modules/**
**/node_modules/**
# Tell docker to ignore **/.node_modules/**
**/.node_modules/**
+80
View File
@@ -0,0 +1,80 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : .env.scripts
# @@Description : Variables for gen-dockerfile and buildx scripts
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/dotenv.template
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# entrypoint Settings
DOCKER_ENTYPOINT_PORTS_WEB="80"
DOCKER_ENTYPOINT_PORTS_SRV="${DOCKER_ENTYPOINT_PORTS_SRV}"
DOCKER_ENTYPOINT_HEALTH_APPS="nginx"
DOCKER_ENTYPOINT_HEALTH_ENDPOINTS="http://localhost/"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Dockerfile info
ENV_DOCKERFILE="Dockerfile"
# ENV_REGISTRY_REPO: Registry repository/image name
ENV_REGISTRY_REPO="super-productivity"
ENV_USE_TEMPLATE="alpine"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Maintainer info
ENV_REGISTRY_ORG="casjaysdevdocker"
ENV_VENDOR="CasjaysDev"
ENV_AUTHOR="CasjaysDev"
ENV_MAINTAINER="CasjaysDev <docker-admin@casjaysdev.pro>"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Repository URLs (Full URLs)
# ENV_GIT_REPO_URL: Complete Git repository URL for source code
ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/super-productivity"
# ENV_REGISTRY_URL: Registry provider base URL (for example https://docker.io)
ENV_REGISTRY_URL="https://docker.io"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Push Configuration
# ENV_REGISTRY_PUSH: Complete push destination derived from registry/org/repo
ENV_REGISTRY_PUSH="casjaysdevdocker/super-productivity"
# ENV_IMAGE_TAG: Default tag for the image
ENV_IMAGE_TAG="latest"
# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag)
ENV_ADD_TAGS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional push destinations (if needed)
ENV_ADD_IMAGE_PUSH=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Pull Configuration
# ENV_PULL_URL: Source image to pull from (base image)
ENV_PULL_URL="casjaysdev/alpine"
# ENV_DISTRO_TAG: Tag for the pull source image
ENV_DISTRO_TAG="${IMAGE_VERSION}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Env
SERVICE_PORT="80"
EXPOSE_PORTS="80"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# IF using a lanuage such as go, php, rust, ruby, etc set the version here.
LANG_VERSION=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Versions
PHP_VERSION="system"
NODE_VERSION="system"
NODE_MANAGER="system"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Default directories
WWW_ROOT_DIR="/usr/local/share/httpd/default"
# - - - - - - - - - - - - - - - - - - - - - - - - -
ENV_PACKAGES="nginx jq curl"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+86
View File
@@ -0,0 +1,86 @@
# Template generated on Sun May 24 11:58:45 AM EDT 2026 from https://github.com/alexkaratarakis/gitattributes"
# Common settings that generally should always be used with your language specific settings
# Auto detect text files and perform LF normalization
* text=auto
# The above will handle all files NOT found below
# Documents
*.bibtex text diff=bibtex
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.md text diff=markdown
*.mdx text diff=markdown
*.tex text diff=tex
*.adoc text
*.textile text
*.mustache text
*.csv text eol=crlf
*.tab text
*.tsv text
*.txt text
*.sql text
*.epub diff=astextplain
# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
# SVG treated as text by default.
*.svg text
# If you want to treat it as binary,
# use the following line instead.
# *.svg binary
*.eps binary
# Scripts
*.bash text eol=lf
*.fish text eol=lf
*.ksh text eol=lf
*.sh text eol=lf
*.zsh text eol=lf
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
# Serialisation
*.json text
*.toml text
*.xml text
*.yaml text
*.yml text
# Archives
*.7z binary
*.bz binary
*.bz2 binary
*.bzip2 binary
*.gz binary
*.lz binary
*.lzma binary
*.rar binary
*.tar binary
*.taz binary
*.tbz binary
*.tbz2 binary
*.tgz binary
*.tlz binary
*.txz binary
*.xz binary
*.Z binary
*.zip binary
*.zst binary
# Text files where line endings should be preserved
*.patch -text
# Exclude files from exporting
.gitattributes export-ignore
.gitignore export-ignore
.gitkeep export-ignore
+86
View File
@@ -0,0 +1,86 @@
name: Build and Push
on:
push:
branches: [main]
schedule:
- cron: '0 2 1 * *'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Compute build metadata
id: meta
run: |
echo "build_date=$(date -u +%Y%m%d%H%M)" >> "$GITHUB_OUTPUT"
echo "tag_yymm=$(date -u +%y%m)" >> "$GITHUB_OUTPUT"
echo "git_commit=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
echo "registry_host=$(echo '${{ github.server_url }}' | sed 's|https://||')" >> "$GITHUB_OUTPUT"
# ── Always: login to Gitea (GITEA_TOKEN is auto-provided) ────────────────
- name: Login to Gitea registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ${{ steps.meta.outputs.registry_host }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITEA_TOKEN }}
# ── Optional: login to external registry when vars.DOCKER_USERNAME is set ──
# vars.DOCKER_REGISTRY defaults to docker.io; set it to push elsewhere.
# Login uses vars.DOCKER_USERNAME; secrets.DOCKER_PASSWORD is passed only
# via with: and never touches a shell.
- name: Login to Docker Hub
if: vars.DOCKER_USERNAME != ''
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ${{ vars.DOCKER_REGISTRY || 'docker.io' }}
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# ── Build once, push to all logged-in registries ─────────────────────────
# Image namespace uses vars.DOCKER_ORG when set, falls back to vars.DOCKER_USERNAME.
# yymm tag pushed first; latest pushed last so registries show :latest as current.
- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ steps.meta.outputs.registry_host }}/${{ github.repository }}:${{ steps.meta.outputs.tag_yymm }}
${{ vars.DOCKER_USERNAME != '' && format('{0}/{1}/{2}:{3}', vars.DOCKER_REGISTRY || 'docker.io', vars.DOCKER_ORG || vars.DOCKER_USERNAME, github.event.repository.name, steps.meta.outputs.tag_yymm) || '' }}
${{ steps.meta.outputs.registry_host }}/${{ github.repository }}:latest
${{ vars.DOCKER_USERNAME != '' && format('{0}/{1}/{2}:{3}', vars.DOCKER_REGISTRY || 'docker.io', vars.DOCKER_ORG || vars.DOCKER_USERNAME, github.event.repository.name, 'latest') || '' }}
build-args: |
BUILD_DATE=${{ steps.meta.outputs.build_date }}
GIT_COMMIT=${{ steps.meta.outputs.git_commit }}
BUILD_VERSION=${{ steps.meta.outputs.tag_yymm }}
annotations: |
org.opencontainers.image.created=${{ steps.meta.outputs.build_date }}
org.opencontainers.image.version=latest
org.opencontainers.image.revision=${{ steps.meta.outputs.git_commit }}
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=Containerized version of ${{ github.event.repository.name }}
org.opencontainers.image.vendor=CasjaysDev
org.opencontainers.image.authors=CasjaysDev
org.opencontainers.image.licenses=WTFPL
org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.documentation=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.vcs-type=Git
com.github.containers.toolbox=false
+242
View File
@@ -0,0 +1,242 @@
# gitignore created on 06/26/26 at 11:56
# Disable reminder in prompt
ignoredirmessage
# ignore .build_failed files
**/.build_failed*
# OS generated files
### Linux ###
# Backup files left by editors
*~
# Temporary files left when a process holds an open handle to a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# NFS stale file handles
.nfs*
### macOS ###
.DS_Store
.DS_Store?
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# iCloud generated files
*.icloud
### Windows ###
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Crash dump files
*.stackdump
# Core dumps (Linux/macOS)
core
core.*
vgcore.*
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### Editors ###
# Visual Studio Code
.vscode/
!.vscode/extensions.json
# JetBrains IDEs (IntelliJ, GoLand, RustRover, PyCharm, etc.)
.idea/
*.iml
*.iws
*.ipr
# Vim / Neovim
*.swp
*.swo
.netrwhist
Session.vim
.vim/
# Sublime Text
*.sublime-workspace
*.sublime-project
# Eclipse / generic Java IDEs
.project
.classpath
.factorypath
.settings/
### AI tool local configs (personal settings, never commit) ###
# Claude Code
.claude/settings.local.json
.claude/*.lock
# Cursor
.cursor/
.cursorignore
.cursorindexingignore
# GitHub Copilot
.copilot/
# Codeium
.codeium/
# Tabnine
.tabnine/
# Aider
.aider/
.aider.conf.yml
.aider.model.settings.yml
.aiderignore
# General AI assistant local state
.ai/
.ai.local/
### Environment and secrets ###
# Local env overrides — never commit credentials
.env
.env.local
.env.*.local
# Private keys and certificates
*.pem
*.key
*.p12
*.pfx
### Build artifacts ###
build/
dist/
out/
# Rust
target/
# C / C++ / compiled objects
*.o
*.a
*.so
*.dylib
*.dll
*.exe
### Dependency directories ###
# Node
node_modules/
# Go (vendored deps are sometimes committed intentionally, so gitignore only the cache)
# vendor/
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.egg-info/
.eggs/
.venv/
venv/
env/
### Logs ###
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
### Temporary and cache ###
tmp/
.tmp/
*.tmp
*.cache
.cache/
### Test and coverage ###
coverage/
.coverage
*.cover
*.coverprofile
htmlcov/
.nyc_output/
.pytest_cache/
.tox/
### Misc — always allow ###
!*/README*
!inc/main.bash
### Project-specific patterns ###
# ignore commit message files
**/.gitcommit
# ignore backup files
**/*.bak
# ignore .no_push files
**/.no_push
**/.nopush
# ignore .no_git files
**/.no_git
# ignore .installed marker files
**/.installed
# ignore work-in-progress rewrite/refactor scripts
**/*.rewrite.sh
**/*.refactor.sh
# ignore local override scripts and configs
**/*.local.sh
**/*.local.conf
**/*.local.yaml
**/*.local.yml
+844
View File
@@ -0,0 +1,844 @@
# Docker Container Repository Specification
## Repository Overview
**Repository:** casjaysdevdocker
**Maintainer:** CasjaysDev <docker-admin@casjaysdev.pro>
**License:** WTFPL / MIT
**Purpose:** Collection of containerized applications using standardized Alpine-based templates
---
## Repository Structure
This repository contains multiple Docker container projects organised as subdirectories. Each project follows a consistent structure and naming convention.
### Directory Layout
```
casjaysdevdocker/
├── ampache/ # Media streaming server
├── apprise/ # Notification service
├── aria2/ # Download manager
├── bind/ # DNS server
├── bun/ # JavaScript runtime
├── caddy/ # Web server
├── code/ # VS Code server
├── couchdb/ # NoSQL database
├── ddns/ # Dynamic DNS client
├── deno/ # JavaScript runtime
├── docker/ # Docker-in-Docker
├── enclosed/ # Encrypted note sharing
├── forgejo/ # Git forge
├── gitea/ # Git service
├── gotify/ # Push notification server
├── i2pd/ # I2P router
├── icecast/ # Audio streaming
├── ifconfig/ # IP info service
├── jekyll/ # Static site generator
├── lighttpd/ # Web server
├── mailman/ # Mailing list manager
├── mariadb/ # SQL database
├── mongodb/ # NoSQL database
├── mpd/ # Music player daemon
├── mysql/ # SQL database
├── navidrome/ # Music streaming
├── neovim/ # Text editor
├── nextcloud/ # Cloud storage
├── nginx/ # Web server
├── nodejs/ # Node.js runtime
├── ntfy/ # Notification service
├── ollama/ # LLM runtime
├── opencloud/ # Cloud platform
├── opengist/ # Gist clone
├── pastebin/ # Pastebin service
├── php/ # PHP runtime
├── podman/ # Container runtime
├── postfix/ # Mail server
├── postgres/ # SQL database
├── proftpd/ # FTP server
├── python/ # Python runtime
├── redis/ # In-memory database
├── soft-serve/ # Git server
├── sqlite/ # SQL database
├── ssl-ca/ # SSL certificate authority
├── tftpd/ # TFTP server
├── tor/ # Tor relay
├── traefik/ # Reverse proxy
├── transmission/ # BitTorrent client
├── valkey/ # Redis fork
├── vim/ # Text editor
├── webmin/ # Web admin interface
├── wordpress/ # CMS platform
├── wttr/ # Weather service
├── xfce4/ # Desktop environment
├── ympd/ # MPD web client
├── youtube-dl/ # Video downloader
└── tools/ # Shared tools & scripts
```
---
## Standard Project Structure
Each project directory contains:
```
project-name/
├── .dockerignore # [generated] Docker build exclusions
├── .env.scripts # [generated] Environment variables for gen-dockerfile
├── .git/ # Git repository
├── .gitattributes # [generated] Git attributes
├── .gitea/workflows/
│ ├── docker.yaml # [hand-crafted] Legacy CI workflow — do not overwrite
│ └── build.yml # [generated] by gen-dockerfile actions — regenerate freely
├── .gitignore # [generated] Git ignore patterns
├── Dockerfile # [generated] Container build definition
├── LICENSE.md # License information
├── README.md # [generated] Project documentation
└── rootfs/ # Container filesystem overlay
├── root/docker/setup/ # [generated] Build-time setup scripts
│ ├── 00-init.sh
│ ├── 01-system.sh
│ ├── 02-packages.sh
│ ├── 03-files.sh
│ ├── 04-users.sh
│ ├── 05-custom.sh
│ ├── 06-post.sh
│ └── 07-cleanup.sh
└── usr/local/
├── bin/
│ ├── entrypoint.sh # [generated] Container entrypoint
│ └── pkmgr # [generated] Package manager wrapper
├── etc/docker/
│ ├── functions/
│ │ └── entrypoint.sh # [generated] Entrypoint functions
│ └── init.d/ # [hand-crafted] Runtime init scripts (one per service)
└── share/template-files/ # [hand-crafted] Config/data templates
├── config/
├── data/
└── defaults/
```
**`[generated]`** — safe to overwrite with `gen-dockerfile --update`; changes will be lost on next regeneration.
**`[hand-crafted]`** — must not be overwritten by gen-dockerfile; customised per container.
---
## gen-dockerfile Tool
All containers are built using the **gen-dockerfile** tool. It generates standardised Dockerfiles, `.env.scripts`, workflow YAML, `pkmgr` scripts, and `rootfs/` scaffolding.
### Usage
```bash
gen-dockerfile [options] [template] [Dockerfile]
gen-dockerfile --dir ./myapp alpine
gen-dockerfile --dir ./myapp --nginx --tag 1.25
gen-dockerfile --dir ./existing-project --update
gen-dockerfile --dir ./myapp actions
```
### Templates (positional argument or `--template`)
| Template | Description | Pull source (build stage) |
|----------|-------------|--------------------------|
| `alpine` | Alpine Linux (default) | `alpine` (Docker Hub official) |
| `arch` / `archlinux` | Arch Linux ARM | `menci/archlinuxarm` |
| `debian` | Debian | `debian` |
| `ubuntu` | Ubuntu | `ubuntu` |
| `rhel` / `almalinux` / `rockylinux` / `centos` / `oraclelinux` / `redhat` | AlmaLinux/RHEL family | `almalinux` |
| `web` | Adds `xorg` + `x11-apps` packages on top of the build stage; scratch final image | `casjaysdev/web` (exists) — override via `ENV_PULL_URL` |
| `xorg` | Adds `xorg` + `x11-apps` packages on top of the build stage; scratch final image | `casjaysdev/xorg` (**does not exist**) — must set `ENV_PULL_URL` |
| `scratch` | Scratch final image only (pair with any build template) | N/A |
> **Note:** The pull source is the base image pulled for the **build stage**. All templates produce a `FROM scratch` final stage. For standard distros (`alpine`, `debian`, `ubuntu`, `rhel`, `arch`), the pull source is the official upstream image. For `web` and `xorg`, gen-dockerfile defaults to `casjaysdev/<template>` when no `ENV_PULL_URL` is set — `casjaysdev/web` exists on Docker Hub; `casjaysdev/xorg` does not. Always set `ENV_PULL_URL` in `.env.scripts` for `xorg` projects.
### CLI Flags
| Flag | Description |
|------|-------------|
| `--dir <path>` | Working directory (default: `$PWD`) |
| `--template <name>` | Override template type |
| `--registry <url>` | Registry provider URL (e.g. `https://docker.io`) |
| `--org <[git\|reg:]name>` | Override org/namespace — prefix `git:` or `reg:` to scope to one system, bare value sets both |
| `--user <[git\|reg:]name>` | Alias for `--org` |
| `--repo <[git\|reg:]name>` | Override repo/image name — same scope prefix rules |
| `--tag <version>` | Image version tag (default: `latest`) |
| `--add-tags <tags>` | Comma-separated additional tags (or `USE_DATE` for auto date tag) |
| `--distro-name <image>` | Base image pull URL (overrides `ENV_PULL_URL`) |
| `--distro-version <tag>` | Base image tag (overrides `ENV_DISTRO_TAG`) |
| `--startup` | Generate an init.d service script at `rootfs/usr/local/etc/docker/init.d/<name>` via `gen-script other start-service`; takes the script filename as a positional argument (e.g. `gen-dockerfile --startup 01-myapp.sh`) |
| `--nogit` | Skip `git init` in the new project dir |
| `--dockerfile` | Regenerate Dockerfile only — skip other files |
| `--update` | Re-run gen-dockerfile on an existing project to regenerate files |
| `--init` | Init mode |
| `--x11` | Enable X11/xorg support |
| `--ports <ports>` | Additional EXPOSE ports |
| `--pkmgr` | Generate `pkmgr` script only and exit |
| `--apache` | Add Apache2 packages + setup |
| `--nginx` | Add nginx packages + setup |
| `--mysql` | Add MariaDB packages + setup (`--mariadb` is handled in the case block but not registered in getopt — use `--mysql`) |
| `--postgres` | Add PostgreSQL packages + setup |
| `--php` | Add PHP packages + setup |
| `--application <name>` | Add a templatemgr application install step |
| `--alpine` / `--almalinux` / `--archlinux` / `--debian` / `--ubuntu` | Shortcut distro flags |
| `--force` | Overwrite existing files without prompting |
| `--silent` | Suppress non-error output |
| `--debug` | Enable `set -x` tracing |
| `--no-color` | Disable colour output |
### Special Subcommands
```bash
gen-dockerfile --dir ./myapp actions
```
Creates `.gitea/workflows/build.yml` (or `build.$version.yml` for versioned tags) from the existing `Dockerfile`. The canonical reference for the legacy hand-written style is `.gitea/workflows/docker.yaml` in the `casjaysdevdocker/.github` org-level repository (`casjaysdevdocker/.github/example/`); `gen-dockerfile actions` generates the modern `build.yml` — use that for all new containers.
### Template Resolution
Templates are loaded from the first match:
1. `$GEN_DOCKERFILE_CONFIG_DIR/templates/<name>.template` (user override)
2. `/usr/local/share/CasjaysDev/scripts/templates/dockerfiles/<name>.template` (installed; also `$CASJAYSDEVDIR/templates/dockerfiles/` when running from a dev checkout)
`template_options.source` is sourced after `__set_variables` runs, allowing template-specific variable overrides.
---
## `.env.scripts` File
Generated at project root; sourced by gen-dockerfile and by the CI workflow at build time.
### Current Variable Names
```bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202601291955-git
# ...
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Entrypoint Settings
DOCKER_ENTYPOINT_PORTS_WEB="${DOCKER_ENTYPOINT_PORTS_WEB}"
DOCKER_ENTYPOINT_PORTS_SRV="${DOCKER_ENTYPOINT_PORTS_SRV}"
DOCKER_ENTYPOINT_HEALTH_APPS="$DOCKER_ENTYPOINT_HEALTH_APPS"
DOCKER_ENTYPOINT_HEALTH_ENDPOINTS="$DOCKER_ENTYPOINT_HEALTH_ENDPOINTS"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Dockerfile info
ENV_DOCKERFILE="Dockerfile"
# ENV_REGISTRY_REPO: Registry repository/image name
ENV_REGISTRY_REPO="myapp"
ENV_USE_TEMPLATE="alpine"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Maintainer info
ENV_REGISTRY_ORG="casjaysdevdocker"
ENV_VENDOR="CasjaysDev"
ENV_AUTHOR="CasjaysDev"
ENV_MAINTAINER="CasjaysDev <docker-admin@casjaysdev.pro>"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Repository URLs (Full URLs)
# ENV_GIT_REPO_URL: Complete Git repository URL for source code
ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/myapp"
# ENV_REGISTRY_URL: Registry provider base URL
ENV_REGISTRY_URL="https://docker.io"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Push Configuration
# ENV_REGISTRY_PUSH: Complete push destination (registry/org/repo)
ENV_REGISTRY_PUSH="casjaysdevdocker/myapp"
# ENV_IMAGE_TAG: Default tag for the image
ENV_IMAGE_TAG="latest"
# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag)
ENV_ADD_TAGS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional push destinations (if needed)
ENV_ADD_IMAGE_PUSH=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Pull Configuration
# ENV_PULL_URL: Source image to pull from (base image)
ENV_PULL_URL="alpine"
# ENV_DISTRO_TAG: Tag for the pull source image
ENV_DISTRO_TAG="${IMAGE_VERSION}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Port exposure
SERVICE_PORT=""
EXPOSE_PORTS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Language runtime version (go, php, rust, ruby, etc)
LANG_VERSION=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Runtime versions
PHP_VERSION="system"
NODE_VERSION="system"
NODE_MANAGER="system"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Default directories
WWW_ROOT_DIR="/usr/local/share/httpd/default"
# - - - - - - - - - - - - - - - - - - - - - - - - -
ENV_PACKAGES=""
```
### Variable Reference
| Variable | Purpose |
|----------|---------|
| `ENV_REGISTRY_REPO` | Image name in the registry |
| `ENV_REGISTRY_ORG` | Organisation/namespace in the registry |
| `ENV_REGISTRY_URL` | Registry base URL (e.g. `https://docker.io`) |
| `ENV_REGISTRY_PUSH` | Full push path `org/repo` (registry host prepended if not `docker.io`) |
| `ENV_ADD_IMAGE_PUSH` | Extra push destinations |
| `ENV_GIT_REPO_URL` | Full Git repository URL |
| `ENV_USE_TEMPLATE` | Template name to use (alpine, debian, etc.) |
| `ENV_PULL_URL` | Base image to pull from |
| `ENV_DISTRO_TAG` | Tag for the base image |
| `ENV_IMAGE_TAG` | Default image tag (default: `latest`) |
| `ENV_ADD_TAGS` | Additional comma-separated tags; `USE_DATE` auto-generates a `YYMM` tag |
| `ENV_PACKAGES` | Space-separated package list to install |
| `ENV_VENDOR` / `ENV_AUTHOR` / `ENV_MAINTAINER` | Label metadata |
| `SERVICE_PORT` | Primary exposed port |
| `EXPOSE_PORTS` | Additional exposed ports |
| `LANG_VERSION` | Language runtime version (go, php, rust, ruby, etc.) |
| `PHP_VERSION` / `NODE_VERSION` / `NODE_MANAGER` | Runtime versions |
| `WWW_ROOT_DIR` | Web root directory (default: `/usr/local/share/httpd/default`) |
| `DOCKER_ENTYPOINT_PORTS_WEB` | Web ports passed to entrypoint |
| `DOCKER_ENTYPOINT_PORTS_SRV` | Service ports passed to entrypoint |
| `DOCKER_ENTYPOINT_HEALTH_APPS` | Apps to health-check |
| `DOCKER_ENTYPOINT_HEALTH_ENDPOINTS` | Endpoints to health-check |
### Legacy Variable Auto-Migration
`gen-dockerfile --update` (and on every run) calls `__migrate_env_script` which automatically renames old variable names to the current ones. Old names that are no longer used:
| Old Name | Current Name |
|----------|-------------|
| `ENV_IMAGE_NAME` | `ENV_REGISTRY_REPO` |
| `ENV_IMAGE_PUSH` | `ENV_REGISTRY_PUSH` |
| `ENV_HUB_BASE` | `ENV_REGISTRY_URL` |
| `ENV_ORG_NAME` | `ENV_REGISTRY_ORG` |
Never use the old names in new `.env.scripts` files.
---
## Dockerfile Template Structure
### Build Arguments
Top-of-file ARGs (before any `FROM`):
| Argument | Description | Default |
|----------|-------------|---------|
| `IMAGE_NAME` | Container name | (from `ENV_REGISTRY_REPO`) |
| `PHP_SERVER` | PHP server name | (same as `IMAGE_NAME`) |
| `BUILD_DATE` | Build timestamp | YYYYMMDDHHMM |
| `LANGUAGE` | System locale | `en_US.UTF-8` |
| `TIMEZONE` | System timezone | `America/New_York` |
| `WWW_ROOT_DIR` | Web root | `/usr/local/share/httpd/default` |
| `PATH` | System `PATH` | `/usr/local/etc/docker/bin:/usr/local/sbin:...` |
| `USER` | Build user | `root` |
| `SHELL_OPTS` | Shell options | `set -e -o pipefail` |
| `SERVICE_PORT` | Primary service port | (from `.env.scripts`) |
| `EXPOSE_PORTS` | Additional ports | (from `.env.scripts`) |
| `PHP_VERSION` | PHP version | `system` |
| `NODE_VERSION` | Node.js version | `system` |
| `NODE_MANAGER` | Node manager | `system` |
| `IMAGE_REPO` | Full push path `org/repo` | (computed) |
| `IMAGE_VERSION` | Image version | `latest` |
| `CONTAINER_VERSION` | Additional image tags | (computed) |
| `PULL_URL` | Base image to pull | `alpine` (official Docker Hub) |
| `DISTRO_VERSION` | Base image tag | `${IMAGE_VERSION}` |
| `BUILD_VERSION` | Build version alias | `${BUILD_DATE}` |
Stage 2 (`FROM scratch`) additional ARGs:
| Argument | Description |
|----------|-------------|
| `TZ` | Timezone alias |
| `GIT_COMMIT` | Git SHA at build time (from CI) |
| `LICENSE` | Image license | default `WTFPL` |
| `ENV_PORTS` | Alias for `${EXPOSE_PORTS}` |
### Generated Dockerfile Structure
#### Stage 1: Build Stage
```dockerfile
FROM tianon/gosu:latest AS gosu
FROM ${PULL_URL}:${DISTRO_VERSION} AS build
# ... ARG declarations ...
ENV ENV=~/.profile
ENV SHELL="/bin/sh"
ENV PATH="${PATH}"
ENV TZ="${TIMEZONE}"
ENV TIMEZONE="${TZ}"
ENV LANG="${LANGUAGE}"
ENV TERM="xterm-256color"
ENV HOSTNAME="casjaysdevdocker-${IMAGE_NAME}"
COPY ./rootfs/. /
RUN pkmgr update; pkmgr install bash ca-certificates; update-ca-certificates
ENV SHELL="/bin/bash"
SHELL ["/bin/bash", "-c"]
COPY --from=gosu /usr/local/bin/gosu /usr/local/bin/gosu
# Setup scripts run in order:
# 00-init.sh - Initialize base system
# 01-system.sh - Configure system settings
# 02-packages.sh - Install/configure packages (after PACK_LIST install)
# 03-files.sh - Copy/modify files
# 04-users.sh - Create users/groups
# 05-custom.sh - Custom application setup
# 06-post.sh - Post-installation tasks
# 07-cleanup.sh - Clean up temporary files
```
#### Stage 2: Final Image
```dockerfile
FROM scratch
# ... ARG and LABEL declarations ...
ENV ENV=~/.bashrc
ENV USER="${USER}"
ENV PATH="${PATH}"
ENV TZ="${TIMEZONE}"
ENV SHELL="/bin/bash"
ENV TIMEZONE="${TZ}"
ENV LANG="${LANGUAGE}"
ENV TERM="xterm-256color"
ENV PORT="${SERVICE_PORT}"
ENV ENV_PORTS="${ENV_PORTS}"
ENV CONTAINER_NAME="${IMAGE_NAME}"
ENV HOSTNAME="casjaysdev-${IMAGE_NAME}"
ENV PHP_SERVER="${PHP_SERVER}"
ENV NODE_VERSION="${NODE_VERSION}"
ENV NODE_MANAGER="${NODE_MANAGER}"
ENV PHP_VERSION="${PHP_VERSION}"
ENV DISTRO_VERSION="${IMAGE_VERSION}"
ENV WWW_ROOT_DIR="${WWW_ROOT_DIR}"
COPY --from=build /. /
VOLUME [ "/config", "/data" ]
EXPOSE ${SERVICE_PORT} ${ENV_PORTS}
STOPSIGNAL SIGRTMIN+3
ENTRYPOINT [ "tini", "-p", "SIGTERM", "--", "/usr/local/bin/entrypoint.sh" ]
HEALTHCHECK --start-period=10m --interval=5m --timeout=15s \
CMD [ "/usr/local/bin/entrypoint.sh", "healthcheck" ]
```
### Container Labels
All containers include OpenContainers standard labels:
```dockerfile
LABEL maintainer="CasjaysDev <docker-admin@casjaysdev.pro>"
LABEL org.opencontainers.image.vendor="CasjaysDev"
LABEL org.opencontainers.image.authors="CasjaysDev"
LABEL org.opencontainers.image.description="Containerized version of ${IMAGE_NAME}"
LABEL org.opencontainers.image.title="${IMAGE_NAME}"
LABEL org.opencontainers.image.base.name="${IMAGE_NAME}"
LABEL org.opencontainers.image.authors="${LICENSE}"
LABEL org.opencontainers.image.created="${BUILD_DATE}"
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
LABEL org.opencontainers.image.schema-version="${BUILD_VERSION}"
LABEL org.opencontainers.image.url="${GEN_DOCKERFILE_HUB_REPO}"
LABEL org.opencontainers.image.source="${GEN_DOCKERFILE_HUB_REPO}"
LABEL org.opencontainers.image.vcs-type="Git"
LABEL org.opencontainers.image.revision="${GIT_COMMIT}"
LABEL org.opencontainers.image.source="${GEN_DOCKERFILE_GIT_REPO}"
LABEL org.opencontainers.image.documentation="${GEN_DOCKERFILE_GIT_REPO}"
LABEL com.github.containers.toolbox="false"
```
> **Note:** `org.opencontainers.image.source` appears twice intentionally — first set to `GEN_DOCKERFILE_HUB_REPO` (computed from `ENV_REGISTRY_URL`/`ENV_REGISTRY_PUSH`), then overridden to `GEN_DOCKERFILE_GIT_REPO` (the Git remote URL). The second value wins at runtime. Neither URL is hardcoded — they reflect whatever registry and org the project is configured for.
---
## Common Package List
Standard packages included in most containers (Alpine template):
```
bash-completion git curl wget sudo unzip iproute2 ssmtp openssl jq tzdata
mailcap ncurses util-linux pciutils usbutils coreutils binutils findutils
grep rsync zip tini py3-pip procps net-tools sed gawk attr readline lsof
less shadow ca-certificates
```
---
## Setup Scripts Convention
Build-time scripts in `rootfs/root/docker/setup/` run inside the Docker build layer.
### 00-init.sh
- Initialize base directory structure
- Set up template directories
- Create initial environment
### 01-system.sh
- Configure APK/apt/yum repositories
- Set up system settings
- Configure locales and timezone
### 02-packages.sh
- Install application-specific packages
- Configure package managers (pip, npm, etc.)
- Set up language runtimes
### 03-files.sh
- Copy configuration files
- Set file permissions
- Create symlinks
### 04-users.sh
- Create application users
- Set up user directories
- Configure user permissions
### 05-custom.sh
- Application-specific installation
- Download/compile software
- Custom configuration
### 06-post.sh
- Post-installation configuration
- Initialize databases
- Generate default configs
### 07-cleanup.sh
- Remove build dependencies
- Clean package caches
- Remove temporary files
---
## Entrypoint System
### Entrypoint Script Flow
```
/usr/local/bin/entrypoint.sh
├─ Load functions from /usr/local/etc/docker/functions/entrypoint.sh
├─ Set up environment variables (sources /root/env.sh, /usr/local/etc/docker/env/*.sh, /config/env/*.sh)
├─ Create /config and /data volumes
├─ Run ALL init scripts from /usr/local/etc/docker/init.d/ (sorted order) via __start_init_scripts
├─ Handle healthcheck command
└─ Execute main application
```
### Init.d Scripts — CRITICAL RULES
**Each service in a repo gets its own numbered init.d script. Never merge or remove them.**
- `__start_init_scripts` iterates and sources **every** `*.sh` file in `init.d/` in sort order.
- Multi-process repos have **one script per service**. Example for a repo running three daemons:
```
init.d/01-named.sh — BIND/named DNS server
init.d/02-nginx.sh — nginx web front-end
init.d/03-php-fpm.sh — PHP-FPM for web UI
```
- **Migration task = UPDATE each script to the canonical pattern, never delete services.**
- The canonical pattern is `04-example.sh` in the `casjaysdevdocker/.github` org-level repository, or generate a fresh one with `gen-dockerfile --startup <name>`.
### Required Variables in Every Init.d Script
```bash
SERVICE_NAME="myapp" # used for PID files, log dirs, config dirs
EXEC_CMD_BIN='myapp' # daemon binary (single-quoted — expanded later)
EXEC_CMD_ARGS='' # daemon arguments (single-quoted)
EXEC_PRE_SCRIPT='' # pre-start script (single-quoted)
SERVICE_USES_PID='' # '' for long-running daemons; 'no' for config-only steps
IS_WEB_SERVER="no" # 'yes' sets RESET_ENV and default port 80
IS_DATABASE_SERVICE="no"
USES_DATABASE_SERVICE="no"
DATABASE_SERVICE_TYPE="sqlite" # custom|sqlite|redis|postgres|mariadb|mysql|couchdb|mongodb|supabase
RUNAS_USER="root"
```
### Hook Functions in Every Init.d Script
The `start-service` template **generates all eleven hook functions** fully implemented inside each init.d script — they are not stubs the developer writes from scratch. The developer customises behaviour via a matching `*_local()` variant that each outer hook calls automatically if defined.
**Outer hooks** (generated, do not redefine):
```bash
__run_precopy() # runs before copying /config to /etc
__execute_prerun() # custom prerun — e.g. set up WWW_ROOT_DIR
__run_pre_execute_checks() # validation before exec; non-zero exitStatus aborts start
__update_conf_files() # runs sed replacements on config files
__pre_execute() # final setup before exec
__post_execute() # background post-start tasks
__pre_message() # message shown before exec
__update_ssl_conf() # SSL certificate setup
__create_service_env() # generates /config/env/$SERVICE_NAME.sh template
__run_start_script() # builds and executes the service start command
__run_secure_function() # chmod 600 on credential files
```
**`*_local()` stubs** (customise these — defined as `{ true; }` by default):
```bash
__run_precopy_local()
__execute_prerun_local()
__run_pre_execute_checks_local()
__update_conf_files_local() # ← put sed/config replacements here
__pre_execute_local()
__post_execute_local()
__pre_message_local()
__update_ssl_conf_local()
```
Each outer hook checks `builtin type -t __<name>_local | grep -q 'function'` before calling the local variant, so stubs that are never overridden cost nothing.
### PID Sentinel Check (CRITICAL)
Every init.d script **must** guard on the correct sentinel file:
```bash
# Correct — dot prefix, no double underscore
if [ ! -f "/run/.start_init_scripts.pid" ]; then
echo "__start_init_scripts function hasn't been Initialized" >&2
SERVICE_IS_RUNNING="no"
__script_exit 1
fi
```
The file is `/run/.start_init_scripts.pid` — a leading dot, no underscores in the filename portion. Any other form silently skips the guard.
### Directory Variables
```bash
DATA_DIR="/data/$SERVICE_NAME" # persistent data
CONF_DIR="/config/$SERVICE_NAME" # persistent config
ETC_DIR="/etc/$SERVICE_NAME" # runtime etc (synced from CONF_DIR)
LOG_DIR="/data/logs/$SERVICE_NAME" # logs
TMP_DIR="/tmp/$SERVICE_NAME"
RUN_DIR="/run/$SERVICE_NAME"
ROOT_FILE_PREFIX="/config/secure/auth/root"
USER_FILE_PREFIX="/config/secure/auth/user"
```
### Volume Mounts
- `/config` — Persistent configuration files
- `/data` — Persistent application data
---
## CI/CD Integration
### Two Workflow Files — Hand-Crafted vs Generated
| File | Origin | Never overwrite? |
|------|--------|-----------------|
| `.gitea/workflows/docker.yaml` | Hand-crafted legacy file; reference copy in `casjaysdevdocker/.github/example/` | Yes — do not overwrite |
| `.gitea/workflows/build.yml` | Generated by `gen-dockerfile actions` | No — regenerate freely |
### Generated Workflow (`gen-dockerfile actions`)
`gen-dockerfile actions` writes `.gitea/workflows/build.yml` (or `build.<version>.yml` for versioned tags) from the current `Dockerfile`. All actions are SHA-pinned.
**Triggers:** `push` to `main`, monthly schedule (`cron: '0 2 1 * *'`), `workflow_dispatch`.
**Registry strategy:**
- Always logs in to the Gitea registry using the auto-provided `GITEA_TOKEN`.
- Conditionally logs in to Docker Hub (or another registry) when `vars.DOCKER_USERNAME` is set; credentials via `vars.DOCKER_USERNAME` + `secrets.DOCKER_PASSWORD`.
- `vars.DOCKER_REGISTRY` overrides the registry URL (default: `docker.io`).
- `vars.DOCKER_ORG` overrides the namespace (fallback: `vars.DOCKER_USERNAME`).
**`build-args` passed:** only `BUILD_DATE`, `GIT_COMMIT`, `BUILD_VERSION` — not `TIMEZONE`, `LANGUAGE`, `LICENSE`, or `TZ`.
**Tags pushed:** `<yymm>` and `latest` to both Gitea and (if configured) Docker Hub.
```yaml
name: Build and Push
on:
push:
branches: [main]
schedule:
- cron: '0 2 1 * *'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Compute build metadata
id: meta
run: |
echo "build_date=$(date -u +%Y%m%d%H%M)" >> "$GITHUB_OUTPUT"
echo "tag_yymm=$(date -u +%y%m)" >> "$GITHUB_OUTPUT"
echo "git_commit=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
echo "registry_host=$(echo '${{ github.server_url }}' | sed 's|https://||')" >> "$GITHUB_OUTPUT"
- name: Login to Gitea registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ${{ steps.meta.outputs.registry_host }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITEA_TOKEN }}
- name: Login to Docker Hub
if: vars.DOCKER_USERNAME != ''
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ${{ vars.DOCKER_REGISTRY || 'docker.io' }}
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ steps.meta.outputs.registry_host }}/${{ github.repository }}:${{ steps.meta.outputs.tag_yymm }}
${{ vars.DOCKER_USERNAME != '' && format('{0}/{1}/{2}:{3}', vars.DOCKER_REGISTRY || 'docker.io', vars.DOCKER_ORG || vars.DOCKER_USERNAME, github.event.repository.name, steps.meta.outputs.tag_yymm) || '' }}
${{ steps.meta.outputs.registry_host }}/${{ github.repository }}:latest
${{ vars.DOCKER_USERNAME != '' && format('{0}/{1}/{2}:{3}', vars.DOCKER_REGISTRY || 'docker.io', vars.DOCKER_ORG || vars.DOCKER_USERNAME, github.event.repository.name, 'latest') || '' }}
build-args: |
BUILD_DATE=${{ steps.meta.outputs.build_date }}
GIT_COMMIT=${{ steps.meta.outputs.git_commit }}
BUILD_VERSION=${{ steps.meta.outputs.tag_yymm }}
annotations: |
org.opencontainers.image.created=${{ steps.meta.outputs.build_date }}
org.opencontainers.image.version=latest
org.opencontainers.image.revision=${{ steps.meta.outputs.git_commit }}
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=Containerized version of ${{ github.event.repository.name }}
org.opencontainers.image.vendor=CasjaysDev
org.opencontainers.image.authors=CasjaysDev
org.opencontainers.image.licenses=WTFPL
org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.documentation=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.vcs-type=Git
com.github.containers.toolbox=false
```
For versioned builds (`gen-dockerfile actions` on a tagged version), the workflow is named `Build and Push <version>`, omits the schedule trigger, and pushes only that fixed version tag.
### Hand-Crafted Workflow (`.gitea/workflows/docker.yaml`)
The legacy `docker.yaml` is hand-crafted; the reference copy lives in `casjaysdevdocker/.github/example/` (the org-level repository). It differs from the generated workflow: uses `catthehacker/ubuntu:act-latest` container, tag-pinned actions (`@v2`/`@v3`/`@v4`), `secrets.DOCKER_USERNAME` + `secrets.DOCKER_TOKEN`, and the old `steps.meta.outputs.*` pattern. Do not use this as a template for new containers — use `gen-dockerfile actions` instead.
---
## Package Manager Wrapper (pkmgr)
The `pkmgr` script in `rootfs/usr/local/bin/pkmgr` provides a unified interface:
```bash
pkmgr update # Update package lists
pkmgr install <pkg> # Install packages
pkmgr remove <pkg> # Remove packages
pkmgr clean # Clean package cache
```
Automatically detects and uses the appropriate package manager (apk, apt-get, dnf, pacman).
---
## Development Workflow
### Creating a New Container
```bash
# 1. Generate scaffolding
gen-dockerfile --dir ./myapp alpine
# 2. Customise .env.scripts (set ENV_REGISTRY_REPO, ENV_REGISTRY_ORG, ports, etc.)
# 3. Customise setup scripts in rootfs/root/docker/setup/
# 4. Generate an init.d runtime script
gen-dockerfile --startup 01-myapp.sh
# 5. Build and test
docker build -t myapp .
docker run -it myapp
# 6. Commit and push to trigger CI/CD
```
### Updating an Existing Container
```bash
# Regenerate Dockerfile and related files from current .env.scripts
gen-dockerfile --dir ./myapp --update
# Regenerate workflow file only
gen-dockerfile --dir ./myapp actions
```
### Adding a New Container from Scratch
1. `gen-dockerfile --dir /path/to/new-container --nogit alpine`
2. Edit `.env.scripts` — set `ENV_REGISTRY_REPO`, `ENV_REGISTRY_PUSH`, `ENV_GIT_REPO_URL`
3. Generate the init.d service script: `gen-dockerfile --startup 01-myapp.sh`
4. Add application-specific setup in `rootfs/root/docker/setup/05-custom.sh`
---
## Project Categories
### Web Servers
- nginx, lighttpd, caddy
### Databases
- mysql, mariadb, postgres, mongodb, couchdb, redis, valkey, sqlite
### Development Tools
- code, neovim, vim, nodejs, python, php, deno, bun
### Container Tools
- docker, podman
### Git Services
- gitea, forgejo, soft-serve, opengist
### Media Services
- ampache, navidrome, mpd, ympd, icecast, youtube-dl
### Networking
- bind, traefik, tor, i2pd, ddns, ifconfig
### Communication
- mailman, postfix, gotify, ntfy, apprise
### Cloud Services
- nextcloud, wordpress
### Utilities
- tools, transmission, aria2, tftpd, ssl-ca, wttr, xfce4, webmin
---
## Resources
- **Docker Hub:** <https://hub.docker.com/u/casjaysdevdocker>
- **Git Repository:** <https://github.com/casjaysdevdocker>
- **gen-dockerfile Tool:** `/usr/local/bin/gen-dockerfile`
- **Template Source:** `/usr/local/share/CasjaysDev/scripts/templates/dockerfiles/` (installed) or `$CASJAYSDEVDIR/templates/dockerfiles/` (dev override)
- **Example Project:** `casjaysdevdocker/.github/example/` (org-level repository — not present in individual container repos)
+135
View File
@@ -0,0 +1,135 @@
# syntax=docker/dockerfile:1
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Super-Productivity Docker Image
# https://github.com/casjaysdevdocker/super-productivity
# - - - - - - - - - - - - - - - - - - - - - - - - -
ARG PULL_URL="casjaysdev/alpine"
ARG DISTRO_VERSION="latest"
# ── Stage 0: pre-built super-productivity web assets ──
FROM johannesjo/super-productivity:latest AS sp-app
# ── Stage 1: gosu binary ──────────────────────────────
FROM tianon/gosu:latest AS gosu
# ── Stage 2: Build stage ──────────────────────────────
FROM ${PULL_URL}:${DISTRO_VERSION} AS build
ARG IMAGE_NAME="super-productivity"
ARG PHP_SERVER="super-productivity"
ARG BUILD_DATE="202501010000"
ARG LANGUAGE="en_US.UTF-8"
ARG TIMEZONE="America/New_York"
ARG WWW_ROOT_DIR="/usr/local/share/httpd/default"
ARG PATH="/usr/local/etc/docker/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ARG USER="root"
ARG SHELL_OPTS="set -e -o pipefail"
ARG SERVICE_PORT="80"
ARG EXPOSE_PORTS="80"
ARG PHP_VERSION="system"
ARG NODE_VERSION="system"
ARG NODE_MANAGER="system"
ARG IMAGE_REPO="casjaysdevdocker/super-productivity"
ARG IMAGE_VERSION="latest"
ARG CONTAINER_VERSION="${IMAGE_VERSION}"
ARG BUILD_VERSION="${BUILD_DATE}"
ENV ENV="~/.profile" \
SHELL="/bin/sh" \
PATH="${PATH}" \
TZ="${TIMEZONE}" \
TIMEZONE="${TIMEZONE}" \
LANG="${LANGUAGE}" \
TERM="xterm-256color" \
HOSTNAME="casjaysdevdocker-${IMAGE_NAME}"
COPY ./rootfs/. /
RUN pkmgr update && pkmgr install bash ca-certificates nginx jq curl && update-ca-certificates
ENV SHELL="/bin/bash"
SHELL ["/bin/bash", "-c"]
COPY --from=gosu /usr/local/bin/gosu /usr/local/bin/gosu
COPY --from=sp-app /usr/share/nginx/html/ /usr/local/share/httpd/default/
RUN chmod -Rf 755 /root/docker/setup && \
/root/docker/setup/00-init.sh && \
/root/docker/setup/01-system.sh && \
/root/docker/setup/02-packages.sh && \
/root/docker/setup/03-files.sh && \
/root/docker/setup/04-users.sh && \
/root/docker/setup/05-custom.sh && \
/root/docker/setup/06-post.sh && \
/root/docker/setup/07-cleanup.sh && \
chmod -Rf 755 /usr/local/etc/docker/init.d && \
chmod +x /usr/local/bin/entrypoint.sh \
/usr/local/bin/pkmgr
# ── Stage 3: Final minimal image ─────────────────────
FROM scratch
ARG BUILD_DATE="202501010000"
ARG GIT_COMMIT=""
ARG IMAGE_NAME="super-productivity"
ARG IMAGE_VERSION="latest"
ARG BUILD_VERSION="${BUILD_DATE}"
ARG LANGUAGE="en_US.UTF-8"
ARG TIMEZONE="America/New_York"
ARG WWW_ROOT_DIR="/usr/local/share/httpd/default"
ARG PATH="/usr/local/etc/docker/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ARG USER="root"
ARG SERVICE_PORT="80"
ARG LICENSE="WTFPL"
ARG ENV_PORTS="80"
ARG TZ="America/New_York"
LABEL maintainer="CasjaysDev <docker-admin@casjaysdev.pro>" \
org.opencontainers.image.vendor="CasjaysDev" \
org.opencontainers.image.authors="CasjaysDev" \
org.opencontainers.image.description="Containerized version of super-productivity" \
org.opencontainers.image.title="${IMAGE_NAME}" \
org.opencontainers.image.base.name="${IMAGE_NAME}" \
org.opencontainers.image.licenses="${LICENSE}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.version="${BUILD_VERSION}" \
org.opencontainers.image.schema-version="${BUILD_VERSION}" \
org.opencontainers.image.url="https://hub.docker.com/r/casjaysdevdocker/super-productivity" \
org.opencontainers.image.source="https://github.com/casjaysdevdocker/super-productivity" \
org.opencontainers.image.vcs-type="Git" \
org.opencontainers.image.revision="${GIT_COMMIT}" \
org.opencontainers.image.documentation="https://github.com/casjaysdevdocker/super-productivity" \
com.github.containers.toolbox="false"
ENV ENV="~/.bashrc" \
USER="${USER}" \
PATH="${PATH}" \
TZ="${TZ}" \
SHELL="/bin/bash" \
TIMEZONE="${TIMEZONE}" \
LANG="${LANGUAGE}" \
TERM="xterm-256color" \
PORT="${SERVICE_PORT}" \
ENV_PORTS="${ENV_PORTS}" \
CONTAINER_NAME="${IMAGE_NAME}" \
HOSTNAME="casjaysdev-${IMAGE_NAME}" \
WWW_ROOT_DIR="${WWW_ROOT_DIR}" \
APP_PORT="80" \
WEBDAV_BACKEND="" \
WEBDAV_BASE_URL="" \
WEBDAV_USERNAME="" \
WEBDAV_SYNC_FOLDER_PATH="" \
SYNC_INTERVAL="" \
IS_COMPRESSION_ENABLED="" \
IS_ENCRYPTION_ENABLED="" \
SUPERSYNC_BASE_URL=""
COPY --from=build /. /
VOLUME ["/config", "/data"]
EXPOSE ${SERVICE_PORT} ${ENV_PORTS}
STOPSIGNAL SIGRTMIN+3
ENTRYPOINT ["tini", "-p", "SIGTERM", "--", "/usr/local/bin/entrypoint.sh"]
HEALTHCHECK --start-period=10m --interval=5m --timeout=15s \
CMD ["/usr/local/bin/entrypoint.sh", "healthcheck"]
+13
View File
@@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2026 casjay <git-admin@casjaysdev.pro>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1. You just DO WHAT THE FUCK YOU WANT TO.
+79
View File
@@ -0,0 +1,79 @@
## 👋 Welcome to super-productivity 🚀
super-productivity README
## Install my system scripts
```shell
sudo bash -c "$(curl -q -LSsf "https://github.com/systemmgr/installer/raw/main/install.sh")"
sudo systemmgr --config && sudo systemmgr install scripts
```
## Automatic install/update
```shell
dockermgr update super-productivity
```
## Install and run container
```shell
dockerHome="/var/lib/srv/$USER/docker/casjaysdevdocker/super-productivity/latest/volumes"
mkdir -p "$dockerHome"
git clone "https://github.com/dockermgr/super-productivity" "$HOME/.local/share/CasjaysDev/dockermgr/super-productivity"
cp -Rfva "$HOME/.local/share/CasjaysDev/dockermgr/super-productivity/volumes/." "$dockerHome/"
docker run -d \
--restart always \
--privileged \
--name casjaysdevdocker-super-productivity-latest \
--hostname super-productivity \
-e TZ=${TIMEZONE:-America/New_York} \
-v "$dockerHome/data:/data:z" \
-v "$dockerHome/config:/config:z" \
-p 80:80 \
casjaysdevdocker/super-productivity:latest
```
## via docker-compose
```yaml
services:
ProjectName:
image: casjaysdevdocker/super-productivity
container_name: casjaysdevdocker-super-productivity
environment:
- TZ=America/New_York
- HOSTNAME=super-productivity
volumes:
- "/var/lib/srv/$USER/docker/casjaysdevdocker/super-productivity/latest/volumes/data:/data:z"
- "/var/lib/srv/$USER/docker/casjaysdevdocker/super-productivity/latest/volumes/config:/config:z"
ports:
- 80:80
restart: always
```
## Get source files
```shell
dockermgr download src casjaysdevdocker/super-productivity
```
OR
```shell
git clone "https://github.com/casjaysdevdocker/super-productivity" "$HOME/Projects/github/casjaysdevdocker/super-productivity"
```
## Build container
```shell
cd "$HOME/Projects/github/casjaysdevdocker/super-productivity"
buildx
```
## Authors
🤖 casjay: [Github](https://github.com/casjay) 🤖
⛵ casjaysdevdocker: [Github](https://github.com/casjaysdevdocker) [Docker](https://hub.docker.com/u/casjaysdevdocker) ⛵
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 00-init.sh
# @@Description : script to run init
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/00-init.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 01-system.sh
# @@Description : script to run system
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/01-system.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 02-packages.sh
# @@Description : script to run packages
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/02-packages.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
if command -v update-ca-certificates >/dev/null 2>&1; then
update-ca-certificates
elif command -v update-ca-trust >/dev/null 2>&1; then
update-ca-trust extract
elif command -v trust >/dev/null 2>&1; then
trust extract-compat
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 03-files.sh
# @@Description : script to run files
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/03-files.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
if [ -d "/etc/nginx" ]; then rm -Rf "/etc/nginx"; fi
if [ -d "/tmp/bin" ]; then
mkdir -p "/usr/local/bin"
for bin in "/tmp/bin"/*; do
[ -e "$bin" ] || continue
name="${bin##*/}"
echo "Installing $name to /usr/local/bin/$name"
cp -Rf "$bin" "/usr/local/bin/$name"
chmod -f +x "/usr/local/bin/$name"
done
fi
unset bin
if [ -d "/tmp/var" ]; then
for var in "/tmp/var"/*; do
[ -e "$var" ] || continue
name="${var##*/}"
echo "Installing $var to /var/$name"
if [ -d "$var" ]; then
mkdir -p "/var/$name"
cp -Rf "$var/." "/var/$name/"
else
cp -Rf "$var" "/var/$name"
fi
done
fi
unset var
if [ -d "/tmp/etc" ]; then
for config in "/tmp/etc"/*; do
[ -e "$config" ] || continue
name="${config##*/}"
echo "Installing $config to /etc/$name"
if [ -d "$config" ]; then
mkdir -p "/etc/$name"
cp -Rf "$config/." "/etc/$name/"
else
cp -Rf "$config" "/etc/$name"
fi
done
fi
unset config
if [ -d "/tmp/usr" ]; then
for share in "/tmp/usr"/*; do
[ -e "$share" ] || continue
name="${share##*/}"
dest="/usr/$name"
echo "Installing $share to $dest"
mkdir -p "$dest"
cp -Rf "$share/." "$dest/"
done
fi
unset share
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 04-users.sh
# @@Description : script to run users
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/04-users.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 05-custom.sh
# @@Description : script to run custom
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/05-custom.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 06-post.sh
# @@Description : script to run post
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/06-post.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261156-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Fri Jun 26 11:56:35 AM EDT 2026
# @@File : 07-cleanup.sh
# @@Description : script to run cleanup
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/07-cleanup.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -eo pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Load functions
__find_and_remove() { [ -z "$1" ] || find "${2:-/etc}" -iname "$1" -exec rm -Rf {} + 2>/dev/null; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
if [ -d "/tmp" ]; then rm -Rf "/tmp"/*; fi
if [ -d "$HOME/.cache" ]; then rm -Rf "$HOME/.cache"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+674
View File
@@ -0,0 +1,674 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606041210-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
# @@ReadME : entrypoint.sh --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Friday, Jun 26, 2026 11:56 EDT
# @@File : entrypoint.sh
# @@Description : Entrypoint file for super-productivity
# @@Changelog : New script
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : other/docker-entrypoint
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run trap command on exit
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' INT TERM
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' SIGPWR 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
[ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ] && export DEBUGGER_OPTIONS="$(<"/config/.debug")" || DEBUGGER_OPTIONS="${DEBUGGER_OPTIONS:-}"
if [ "$DEBUGGER" = "on" ] || [ -f "/config/.debug" ]; then
echo "Enabling debugging"
set -eo pipefail
[ -n "$DEBUGGER_OPTIONS" ] && set -"$DEBUGGER_OPTIONS"
export DEBUGGER="on"
else
set -eo pipefail
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
PATH="/usr/local/etc/docker/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
SCRIPT_FILE="$0"
CONTAINER_NAME="super-productivity"
SCRIPT_NAME="${SCRIPT_FILE##*/}"
CONTAINER_NAME="${ENV_CONTAINER_NAME:-$CONTAINER_NAME}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# remove whitespaces from beginning argument
while :; do [ "$1" = " " ] && shift 1 || break; done
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ "$1" = "$SCRIPT_FILE" ] && shift 1
[ "$1" = "$SCRIPT_NAME" ] && shift 1
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import the functions file
if [ -f "/usr/local/etc/docker/functions/entrypoint.sh" ]; then
. "/usr/local/etc/docker/functions/entrypoint.sh"
else
echo "Can not load functions from /usr/local/etc/docker/functions/entrypoint.sh"
exit 1
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
case "$1" in
# Help message
-h | --help)
shift 1
echo "Docker container for $CONTAINER_NAME"
echo "Usage: $CONTAINER_NAME [help tail cron exec start init shell procs ports healthcheck backup command]"
echo ""
exit 0
;;
-*)
shift
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Create the default env files
__create_env_file "/config/env/default.sh" "/root/env.sh" &>/dev/null
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import variables from files
for set_env in "/root/env.sh" "/usr/local/etc/docker/env"/*.sh "/config/env"/*.sh; do
[ -f "$set_env" ] && . "$set_env"
done
unset set_env
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User to use to launch service - IE: postgres
# normally root
RUNAS_USER="root"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set user and group from env
SERVICE_USER="${PUID:-$SERVICE_USER}"
SERVICE_GROUP="${PGID:-$SERVICE_GROUP}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set user and group ID
# set the user id
SERVICE_UID="${SERVICE_UID:-0}"
# set the group id
SERVICE_GID="${SERVICE_GID:-0}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User and group in which the service switches to - IE: nginx,apache,mysql,postgres
#SERVICE_USER="${SERVICE_USER:-super-productivity}" # execute command as another user
#SERVICE_GROUP="${SERVICE_GROUP:-super-productivity}" # Set the service group
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Secondary ports
# specifiy other ports
SERVER_PORTS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Primary server port- will be added to server ports
# port : 80,443
WEB_SERVER_PORT=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Healthcheck variables
# enable healthcheck [yes/no]
HEALTH_ENABLED="yes"
# comma separated list of processes for the healthcheck
SERVICES_LIST="tini"
# url endpoints: [http://localhost/health,http://localhost/test]
HEALTH_ENDPOINTS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Update path var
export PATH RUNAS_USER SERVICE_USER SERVICE_GROUP SERVICE_UID SERVICE_GID WWW_ROOT_DIR DATABASE_DIR
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom variables
# - - - - - - - - - - - - - - - - - - - - - - - - -
# show message
__run_message() {
return
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
################## END OF CONFIGURATION #####################
# Lets get containers ip address
IP4_ADDRESS="$(__get_ip4)"
IP6_ADDRESS="$(__get_ip6)"
CONTAINER_IP4_ADDRESS="${CONTAINER_IP4_ADDRESS:-$IP4_ADDRESS}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Startup variables
export INIT_DATE="${INIT_DATE:-$(date)}"
export CONTAINER_INIT="${CONTAINER_INIT:-no}"
export START_SERVICES="${START_SERVICES:-no}"
export ENTRYPOINT_MESSAGE="${ENTRYPOINT_MESSAGE:-yes}"
export ENTRYPOINT_FIRST_RUN="${ENTRYPOINT_FIRST_RUN:-yes}"
export DATA_DIR_INITIALIZED="${DATA_DIR_INITIALIZED:-no}"
export CONFIG_DIR_INITIALIZED="${CONFIG_DIR_INITIALIZED:-no}"
export CONTAINER_NAME="${ENV_CONTAINER_NAME:-$CONTAINER_NAME}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# System
export LANG="${LANG:-C.UTF-8}"
export LC_ALL="${LANG:-C.UTF-8}"
export TZ="${TZ:-${TIMEZONE:-America/New_York}}"
export HOSTNAME="$(hostname -s)"
export DOMAINNAME="$(hostname -d)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Default directories
export SSL_DIR="${SSL_DIR:-/config/ssl}"
export SSL_CA="${SSL_CA:-/config/ssl/ca.crt}"
export SSL_KEY="${SSL_KEY:-/config/ssl/localhost.pem}"
export SSL_CERT="${SSL_CERT:-/config/ssl/localhost.crt}"
export LOCAL_BIN_DIR="${LOCAL_BIN_DIR:-/usr/local/bin}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Backup settings
export BACKUP_MAX_DAYS="${BACKUP_MAX_DAYS:-}"
export BACKUP_RUN_CRON="${BACKUP_RUN_CRON:-}"
export BACKUP_DIR="${BACKUP_DIR:-/data/backups}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional
export PHP_INI_DIR="${PHP_INI_DIR:-$(__find_php_ini)}"
export PHP_BIN_DIR="${PHP_BIN_DIR:-$(__find_php_bin)}"
export HTTPD_CONFIG_FILE="${HTTPD_CONFIG_FILE:-$(__find_httpd_conf)}"
export NGINX_CONFIG_FILE="${NGINX_CONFIG_FILE:-$(__find_nginx_conf)}"
export MYSQL_CONFIG_FILE="${MYSQL_CONFIG_FILE:-$(__find_mysql_conf)}"
export PGSQL_CONFIG_FILE="${PGSQL_CONFIG_FILE:-$(__find_pgsql_conf)}"
export MONGODB_CONFIG_FILE="${MONGODB_CONFIG_FILE:-$(__find_mongodb_conf)}"
export ENTRYPOINT_PID_FILE="${ENTRYPOINT_PID_FILE:-/run/.entrypoint.pid}"
export ENTRYPOINT_INIT_FILE="${ENTRYPOINT_INIT_FILE:-/config/.entrypoint.done}"
export ENTRYPOINT_DATA_INIT_FILE="${ENTRYPOINT_DATA_INIT_FILE:-/data/.docker_has_run}"
export ENTRYPOINT_CONFIG_INIT_FILE="${ENTRYPOINT_CONFIG_INIT_FILE:-/config/.docker_has_run}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -n "$CONTAINER_WEB_SERVER_WWW_REPO" ]; then
www_temp_dir="/tmp/git/${CONTAINER_WEB_SERVER_WWW_REPO##*/}"
rm -Rf "${WWW_ROOT_DIR:?}"/* "${www_temp_dir:?}"/* 2>/dev/null || true
mkdir -p "$WWW_ROOT_DIR" "$www_temp_dir" 2>/dev/null || true
git clone -q "$CONTAINER_WEB_SERVER_WWW_REPO" "$www_temp_dir" 2>/dev/null || true
rm -Rf "$www_temp_dir/.git" "$www_temp_dir"/.git* 2>/dev/null || true
rsync -ra "$www_temp_dir/" "$WWW_ROOT_DIR" --delete 2>/dev/null || true
rm -Rf "$www_temp_dir" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# variables based on env/files
if [ -f "/config/enable/ssl" ]; then SSL_ENABLED="yes"; fi
if [ -f "/config/enable/ssh" ]; then SSH_ENABLED="yes"; fi
if [ "$WEB_SERVER_PORT" = "443" ]; then SSL_ENABLED="yes"; fi
if [ "$CONTAINER_WEB_SERVER_PROTOCOL" = "https" ]; then SSL_ENABLED="yes"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# export variables
# - - - - - - - - - - - - - - - - - - - - - - - - -
# is already Initialized
if [ -f "$ENTRYPOINT_DATA_INIT_FILE" ]; then
DATA_DIR_INITIALIZED="yes"
else
DATA_DIR_INITIALIZED="no"
fi
if [ -f "$ENTRYPOINT_CONFIG_INIT_FILE" ]; then
CONFIG_DIR_INITIALIZED="yes"
else
CONFIG_DIR_INITIALIZED="no"
fi
if [ -f "$ENTRYPOINT_PID_FILE" ] || [ -f "$ENTRYPOINT_INIT_FILE" ]; then
ENTRYPOINT_FIRST_RUN="no"
else
ENTRYPOINT_FIRST_RUN="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean ENV_PORTS variables
ENV_PORTS="${ENV_PORTS//,/ }"
ENV_PORTS="${ENV_PORTS//\/*/}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean SERVER_PORTS variables
SERVER_PORTS="${SERVER_PORTS//,/ }"
SERVER_PORTS="${SERVER_PORTS//\/*/}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean WEB_SERVER_PORTS variables
WEB_SERVER_PORTS="${WEB_SERVER_PORT//,/ } ${ENV_WEB_SERVER_PORTS//,/ }"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# rewrite and merge variables
ENV_PORTS="$(__format_variables "$ENV_PORTS" || false)"
WEB_SERVER_PORTS="$(__format_variables "$WEB_SERVER_PORTS" || false)"
ENV_PORTS="$(__format_variables "$SERVER_PORTS" "$WEB_SERVER_PORTS" "$ENV_PORTS" "$SERVER_PORTS" || false)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Remove the commas from env
HEALTH_ENDPOINTS="${HEALTH_ENDPOINTS//,/ }"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create required directories
mkdir -p "/run" 2>/dev/null || true
mkdir -p "/tmp" 2>/dev/null || true
mkdir -p "/root" 2>/dev/null || true
mkdir -p "/var/run" 2>/dev/null || true
mkdir -p "/var/tmp" 2>/dev/null || true
mkdir -p "/run/cron" 2>/dev/null || true
mkdir -p "/data/logs" 2>/dev/null || true
mkdir -p "/run/init.d" 2>/dev/null || true
mkdir -p "/config/enable" 2>/dev/null || true
mkdir -p "/config/secure" 2>/dev/null || true
mkdir -p "/usr/local/etc/docker/exec" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create required files
touch "/data/logs/start.log" 2>/dev/null || true
touch "/data/logs/entrypoint.log" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# fix permissions
chmod -f 777 "/run" 2>/dev/null || true
chmod -f 777 "/tmp" 2>/dev/null || true
chmod -f 700 "/root" 2>/dev/null || true
chmod -f 777 "/var/run" 2>/dev/null || true
chmod -f 777 "/var/tmp" 2>/dev/null || true
chmod -f 777 "/run/cron" 2>/dev/null || true
chmod -f 777 "/data/logs" 2>/dev/null || true
chmod -f 777 "/run/init.d" 2>/dev/null || true
chmod -f 777 "/config/enable" 2>/dev/null || true
chmod -f 777 "/config/secure" 2>/dev/null || true
chmod -f 777 "/data/logs/entrypoint.log" 2>/dev/null || true
chmod -f 777 "/usr/local/etc/docker/exec" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# lets ensure everyone can write to std*
if [ -f "/dev/stdin" ]; then
chmod -f 777 "/dev/stdin" 2>/dev/null || true
fi
if [ -f "/dev/stderr" ]; then
chmod -f 777 "/dev/stderr" 2>/dev/null || true
fi
if [ -f "/dev/stdout" ]; then
chmod -f 777 "/dev/stdout" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
cat <<EOF 2>/dev/null | tee /etc/profile.d/locales.shadow /etc/profile.d/locales.sh >/dev/null 2>&1 || true
export LANG="\${LANG:-C.UTF-8}"
export LC_ALL="\${LANG:-C.UTF-8}"
export TZ="\${TZ:-\${TIMEZONE:-America/New_York}}"
EOF
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Create the backup dir
if [ -n "$BACKUP_DIR" ]; then
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "$ENTRYPOINT_INIT_FILE" ]; then
ENTRYPOINT_MESSAGE="no" ENTRYPOINT_FIRST_RUN="no"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
if [ "$CONFIG_DIR_INITIALIZED" = "no" ] || [ "$DATA_DIR_INITIALIZED" = "no" ]; then
if [ "$ENTRYPOINT_MESSAGE" = "yes" ]; then
echo "Executing entrypoint script for super-productivity"
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set reusable variables
if [ -w "/etc" ] && [ ! -f "/etc/hosts" ]; then
UPDATE_FILE_HOSTS="yes"
touch "/etc/hosts"
elif [ -w "/etc/hosts" ]; then
UPDATE_FILE_HOSTS="yes"
touch "/etc/hosts"
fi
if [ -w "/etc" ] && [ ! -f "/etc/timezone" ]; then
UPDATE_FILE_TZ="yes"
touch "/etc/timezone"
elif [ -w "/etc/timezone" ]; then
UPDATE_FILE_TZ="yes"
touch "/etc/timezone"
fi
if [ -w "/etc" ] && [ ! -f "/etc/resolv.conf" ]; then
UPDATE_FILE_RESOLV="yes"
touch "/etc/resolv.conf"
elif [ -w "/etc/resolv.conf" ]; then
UPDATE_FILE_RESOLV="yes"
touch "/etc/resolv.conf"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set timezone
if [ -n "$TZ" ] && [ "$UPDATE_FILE_TZ" = "yes" ]; then
echo "$TZ" >"/etc/timezone" 2>/dev/null || true
fi
if [ -f "/usr/share/zoneinfo/$TZ" ] && [ "$UPDATE_FILE_TZ" = "yes" ]; then
ln -sf "/usr/share/zoneinfo/$TZ" "/etc/localtime" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# if ipv6 add it to /etc/hosts
if [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
echo "# known hostname mappings" >"/etc/hosts" 2>/dev/null || true
if [ -n "$(ip a 2>/dev/null | grep 'inet6.*::' || ifconfig 2>/dev/null | grep 'inet6.*::')" ]; then
__printf_space "40" "::1" "localhost" >>"/etc/hosts" 2>/dev/null || true
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
else
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# add .internal domain
if [ "$UPDATE_FILE_HOSTS" = "yes" ] && [ -n "$HOSTNAME" ]; then
if ! __grep_test " $HOSTNAME" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "$HOSTNAME" >>"/etc/hosts" 2>/dev/null || true
fi
if ! __grep_test " ${HOSTNAME%%.*}.internal" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "${HOSTNAME%%.*}.internal" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# add domainname
if [ "$UPDATE_FILE_HOSTS" = "yes" ] && [ "$DOMAINNAME" != "internal" ] && [ -n "$DOMAINNAME" ] && [ "$HOSTNAME.$DOMAINNAME" != "$DOMAINNAME" ]; then
if ! __grep_test " ${HOSTNAME%%.*}.$DOMAINNAME" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "${HOSTNAME%%.*}.$DOMAINNAME" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set containers hostname
if [ -n "$HOSTNAME" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
echo "$HOSTNAME" >"/etc/hostname" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "/etc/hostname" ]; then
if command -v hostname &>/dev/null; then
hostname -F "/etc/hostname" 2>/dev/null || true
else
HOSTNAME="$(<"/etc/hostname")" 2>/dev/null || true
fi
export HOSTNAME
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import hosts file into container
if [ -f "/usr/local/etc/hosts" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
grep -vF "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import resolv.conf file into container
if [ "$CUSTOM_DNS" != "yes" ] && [ -f "/usr/local/etc/resolv.conf" ] && [ "$UPDATE_FILE_RESOLV" = "yes" ]; then
cp -f "/usr/local/etc/resolv.conf" "/etc/resolv.conf" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -n "$HOME" ] && [ -d "/usr/local/etc/skel" ]; then
if [ -d "$HOME" ]; then
cp -Rf "/usr/local/etc/skel/." "$HOME/" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Delete any .gitkeep files (bash * does not match dotfiles by default,
# so the explicit /.gitkeep path is required at each depth)
if [ -d "/data" ]; then
rm -Rf "/data/.gitkeep" "/data"/*/.gitkeep 2>/dev/null || true
fi
if [ -d "/config" ]; then
rm -Rf "/config/.gitkeep" "/config"/*/.gitkeep 2>/dev/null || true
fi
if [ -f "/usr/local/bin/.gitkeep" ]; then
rm -Rf "/usr/local/bin/.gitkeep" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Only run initialization on first run or when directories are not initialized
if [ "$ENTRYPOINT_FIRST_RUN" != "no" ] || [ "$CONFIG_DIR_INITIALIZED" = "no" ] || [ "$DATA_DIR_INITIALIZED" = "no" ]; then
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Setup bin directory - /config/bin > /usr/local/bin
__initialize_custom_bin_dir
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Initialize SSL certificates
__initialize_ssl_certs
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Mark directories as initialized (only write if not already initialized)
if [ -d "/config" ] && [ "$CONFIG_DIR_INITIALIZED" = "no" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_CONFIG_INIT_FILE" 2>/dev/null || true
CONFIG_DIR_INITIALIZED="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -d "/data" ] && [ "$DATA_DIR_INITIALIZED" = "no" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_DATA_INIT_FILE" 2>/dev/null || true
DATA_DIR_INITIALIZED="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -d "/config" ] && [ ! -f "$ENTRYPOINT_INIT_FILE" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_INIT_FILE" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup the smtp server
__setup_mta
# - - - - - - - - - - - - - - - - - - - - - - - - -
ENTRYPOINT_FIRST_RUN="no"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# if no pid assume container restart - clean stale files on restart
if [ -f "$ENTRYPOINT_PID_FILE" ]; then
# Check if the PID in the file is still running
entrypoint_pid=$(<"$ENTRYPOINT_PID_FILE") 2>/dev/null
if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null; then
# Process is still running, don't restart services
START_SERVICES="no"
touch "$ENTRYPOINT_PID_FILE"
else
# PID file exists but process is dead - this is a restart
START_SERVICES="yes"
# Clean any stale PID files on restart
rm -f /run/.start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
fi
else
START_SERVICES=yes
# Clean any stale PID files on first run
rm -f /run/.start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ "$ENTRYPOINT_MESSAGE" = "yes" ] && __printf_space "40" "The containers ip address is:" "$CONTAINER_IP4_ADDRESS"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Show configured listing processes
if [ "$ENTRYPOINT_MESSAGE" = "yes" ] && [ -n "$ENV_PORTS" ]; then
show_port=""
for port in $ENV_PORTS; do [ -n "$port" ] && show_port+="$(printf '%s ' "${port// /}") "; done
__printf_space "40" "The following ports are open:" "$show_port"
unset port show_port
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# execute init script
if [ -f "/tmp/init" ]; then sh "/tmp/init"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create user if needed
__create_service_user "$SERVICE_USER" "$SERVICE_GROUP" "${WORK_DIR:-/home/$SERVICE_USER}" "${SERVICE_UID:-}" "${SERVICE_GID:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Modify user if needed
__set_user_group_id $SERVICE_USER ${SERVICE_UID:-} ${SERVICE_GID:-}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Show message
__run_message
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Just start services
START_SERVICES="${START_SERVICES:-yes}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Determine if we should start services based on command
# Only skip service start for the 'init' command
SKIP_SERVICE_START="no"
[ "$1" = "init" ] && SKIP_SERVICE_START="yes" && CONTAINER_INIT="yes"
[ "$2" = "init" ] && SKIP_SERVICE_START="yes" && CONTAINER_INIT="yes"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Start all services if no pidfile and not skipping
if [ "$START_SERVICES" = "yes" ] || [ -z "$1" ]; then
if [ "$SKIP_SERVICE_START" = "no" ]; then
[ "$1" = "start" ] && shift 1
[ "$1" = "all" ] && shift 1
rm -Rf "/run"/*/*pid 2>/dev/null || true
echo "$$" >"$ENTRYPOINT_PID_FILE"
__start_init_scripts "/usr/local/etc/docker/init.d"
CONTAINER_INIT="${CONTAINER_INIT:-no}"
# Services started successfully - enter monitoring mode
__no_exit
exit $?
fi
START_SERVICES="no"
fi
export START_SERVICES CONTAINER_INIT ENTRYPOINT_PID_FILE
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Begin options
case "$1" in
init)
shift 1
__log_info "Container has been initialized"
exit 0
;;
tail)
shift 1
case "$1" in
null)
shift $#
tail -F "/dev/null"
;;
app)
shift $#
tail -F /data/logs/*/*.log
;;
-*)
tail "$@"
;;
*)
tail -F "${@:-/dev/null}"
;;
esac
;;
logs)
shift 1
case "$1" in
follow)
tail -Fq /data/logs/*/*
;;
clean)
mapfile -t log_files < <(find "/data/logs" -type f 2>/dev/null)
for log in "${log_files[@]}"; do
__log_info "Clearing log file: $log"
printf '' >"$log"
done
;;
*)
echo "Usage: logs [follow,clean]"
exit 0
;;
esac
;;
cron)
shift 1
__cron "$@" &
__log_info "Cron script is running with PID: $!"
exit
;;
# backup data and config dirs
backup)
shift 1
__backup $BACKUP_MAX_DAYS $1
exit $?
;;
# Docker healthcheck
healthcheck)
shift 1
case "$1" in
init | test)
exit 0
;;
*)
arguments="$*"
healthStatus=0
healthEnabled="${HEALTH_ENABLED:-}"
healthPorts="${WEB_SERVER_PORTS:-}"
healthEndPoints="${HEALTH_ENDPOINTS:-}"
SERVICES_LIST="${arguments:-$SERVICES_LIST}"
services="${SERVICES_LIST//,/ }"
healthMessage="Everything seems to be running"
[ "$healthEnabled" = "yes" ] || exit 0
if [ -d "/run/healthcheck" ] && ! __is_dir_empty "/run/healthcheck"; then
for service in /run/healthcheck/*; do
name="${service##*/}"
services+="$name "
done
fi
services="$(printf '%s\n' $services | sort -u | grep -v '^$')"
for proc in $services; do
if [ -n "$proc" ]; then
if ! __pgrep "$proc"; then
echo "$proc is not running" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
for port in $healthPorts; do
if command -v netstat &>/dev/null && [ -n "$port" ]; then
if ! netstat -taupln | grep -q ":$port "; then
echo "$port isn't open" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
for endpoint in $healthEndPoints; do
if [ -n "$endpoint" ]; then
if ! __curl "$endpoint"; then
echo "Can not connect to $endpoint" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
[ "$healthStatus" -eq 0 ] || healthMessage="Errors reported see: docker logs --follow $CONTAINER_NAME"
[ -n "$healthMessage" ] && echo "$healthMessage"
exit $healthStatus
;;
esac
;;
# show open ports
ports)
shift 1
ports="$(__netstat -taupln 2>/dev/null | awk '{ split($4, a, ":"); if (a[2] != "") print a[2] }' | sort -uV)"
[ -n "$ports" ] && printf '%s\n%s\n' "The following are servers:" "$ports" | tr '\n' ' '
exit $?
;;
# show running processes
procs)
shift 1
ps="$(__ps axco command 2>/dev/null | grep -vE '^(COMMAND|grep|ps)$' | sort -u)"
[ -n "$ps" ] && printf '%s\n%s\n' "Found the following processes" "$ps" | tr '\n' ' '
exit $?
;;
# Launch shell
*/bin/sh | */bin/bash | bash | sh | shell)
shift 1
__exec_command "${@:-/bin/bash -l}"
exit $?
;;
# execute commands
exec)
shift 1
__exec_command "${@:-echo "No commands given"}"
exit $?
;;
# show/start init scripts
start)
shift 1
export PATH="/usr/local/etc/docker/init.d:$PATH"
if [ $# -eq 0 ]; then
scripts="$(ls -A "/usr/local/etc/docker/init.d")"
[ -n "$scripts" ] && echo "$scripts" || echo "No scripts found in: /usr/local/etc/docker/init.d"
exit
elif [ "$1" = "all" ]; then
shift $#
if [ "$START_SERVICES" = "yes" ]; then
echo "$$" >"$ENTRYPOINT_PID_FILE"
__start_init_scripts "/usr/local/etc/docker/init.d"
__no_exit
elif [ -f "/usr/local/etc/docker/init.d/$1" ]; then
eval "/usr/local/etc/docker/init.d/$1" &
__no_exit
fi
fi
;;
# Execute primary command
*)
if [ $# -eq 0 ]; then
if [ ! -f "$ENTRYPOINT_PID_FILE" ]; then
echo "$$" >"$ENTRYPOINT_PID_FILE"
[ "$START_SERVICES" = "no" ] && [ "$CONTAINER_INIT" = "yes" ] || __start_init_scripts "/usr/local/etc/docker/init.d"
fi
__no_exit
else
__exec_command "$@"
fi
exit $?
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# end of entrypoint
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/env sh
# shellcheck shell=sh
# shellcheck disable=SC2016
# - - - - - - - - - - - - - - - - - - - - - - - - -
USER_UID="$(id -u)"
USER_GID="$(id -g)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -x "$(command -v apt 2>/dev/null)" ]; then
export DEBIAN_FRONTEND=noninteractive
pkmgr_cmd="apt"
pkmgr_clean_cmd="$pkmgr_cmd clean"
pkmgr_mkcache_cmd="$pkmgr_cmd update"
pkmgr_update_cmd="$pkmgr_cmd upgrade -yy"
pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS"
pkmgr_install_post="$pkmgr_cmd --fix-broken install"
elif [ -x "$(command -v apt-get 2>/dev/null)" ]; then
export DEBIAN_FRONTEND=noninteractive
pkmgr_cmd="apt-get"
pkmgr_clean_cmd="$pkmgr_cmd clean"
pkmgr_mkcache_cmd="$pkmgr_cmd update"
pkmgr_update_cmd="$pkmgr_cmd upgrade -yy"
pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS"
pkmgr_install_post="$pkmgr_cmd --fix-broken install"
elif [ -x "$(command -v dnf 2>/dev/null)" ]; then
pkmgr_cmd="dnf"
pkmgr_clean_cmd="$pkmgr_cmd clean all"
pkmgr_mkcache_cmd="$pkmgr_cmd makecache"
pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS"
elif [ -x "$(command -v yum 2>/dev/null)" ]; then
pkmgr_cmd="yum"
pkmgr_clean_cmd="$pkmgr_cmd clean all"
pkmgr_mkcache_cmd="$pkmgr_cmd makecache"
pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS"
elif [ -n "$(command -v pacman 2>/dev/null)" ]; then
pkmgr_cmd="pacman"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd -Scc --noconfirm"
pkmgr_update_cmd="$pkmgr_cmd -Syyu --noconfirm $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd -Syy --noconfirm $PKMGR_OPTS"
elif [ -x "$(command -v apk 2>/dev/null)" ]; then
pkmgr_cmd="apk"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd cache clean"
pkmgr_update_cmd="$pkmgr_cmd -U upgrade --no-cache $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd add --no-cache $PKMGR_OPTS"
elif [ -x "$(command -v zypper 2>/dev/null)" ]; then
pkmgr_cmd="zypper"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd clean --all"
pkmgr_update_cmd="$pkmgr_cmd update -y $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y $PKMGR_OPTS"
else
pkmgr_cmd="true"
pkmgr_mkcache_cmd="$pkmgr_cmd"
pkmgr_clean_cmd="$pkmgr_cmd"
pkmgr_update_cmd="$pkmgr_cmd"
pkmgr_install_cmd="$pkmgr_cmd"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "/config/pkmgr/settings.conf" ]; then
. "/config/pkmgr/settings.conf"
elif [ -f "/etc/pkmgr/settings.conf" ]; then
. "/etc/pkmgr/settings.conf"
else
mkdir -p "/config/pkmgr"
cat <<EEOF >"/config/pkmgr/settings.conf"
pkmgr_cmd="$pkmgr_cmd"
pkmgr_clean_cmd="$pkmgr_clean_cmd"
pkmgr_update_cmd="$pkmgr_update_cmd"
pkmgr_install_cmd="$pkmgr_install_cmd"
pkmgr_mkcache_cmd="$pkmgr_mkcache_cmd"
EEOF
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ -n "$pkmgr_cmd" ] || { echo "Can not determine the package manager" && exit 1; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
case "$1" in
pip)
shift 1
pip_bin="$(command -v python3 2>/dev/null || command -v python2 2>/dev/null || command -v python 2>/dev/null || echo "")"
py_version="$($pip_bin --version | sed 's|[pP]ython ||g' | awk -F '.' '{print $1$2}' | grep '[0-9]' || echo "0")"
[ "$py_version" -gt "310" ] && pip_opts="--break-system-packages " || pip_opts=""
case "$1" in
install)
shift 1
pkg_list="$*"
for pkg in $pkg_list; do
$pip_bin -m pip $pip_opts "$pkg"
done
;;
*)
for pkg in "$@"; do
$pip_bin -m pip "$pkg"
done
;;
esac
exit
;;
install)
shift 1
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_install_cmd="sudo $pkmgr_install_cmd"
if [ -f "$1" ]; then
install_list="$(tr '\n' ' ' < "$1")"
else
install_list="$*"
fi
for pkg in $install_list;do
echo "installing packages command: $pkmgr_install_cmd $pkg"
$pkmgr_install_cmd $pkg
if [ -n "$pkmgr_install_post" ]; then eval $pkmgr_install_post; fi
done
exit
;;
update | upgrade)
shift $#
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_update_cmd="sudo $pkmgr_install_cmd"
echo "Updating packages command: $pkmgr_update_cmd"
$pkmgr_mkcache_cmd
$pkmgr_update_cmd
exit $?
;;
clean)
shift $#
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_clean_cmd="sudo $pkmgr_clean_cmd"
echo "Cleaning package cache: $pkmgr_clean_cmd"
$pkmgr_clean_cmd
exit $?
;;
*)
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_cmd="sudo $pkmgr_cmd"
echo "executing packages command: $pkmgr_cmd $*"
$pkmgr_cmd "$@"
exit $?
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff