Gogs — Structure#
Layout pattern#
Standard Go Layout (cmd/internal), no pkg/
Gogs uses the canonical cmd/ + internal/ layout with no public pkg/ directory — all application code is encapsulated under internal/. This reflects a deliberate decision that Gogs is an application, not a library, with no intent to expose importable packages to external consumers. The layout is straightforward: one binary, one cmd subdirectory, one large internal tree.
Directory map#
gogs/
├── cmd/gogs/ # Single binary entry point; 9 files, 7 subcommands
├── conf/ # Embedded config assets: locales (31 langs), gitignore templates,
│ ├── auth.d/ # auth source templates
│ ├── gitignore/ # .gitignore templates for new repos
│ ├── label/ # default issue label sets
│ ├── license/ # license templates
│ ├── locale/ # i18n translation files
│ └── readme/ # readme templates
├── docker/ # Docker build + runtime + s6 supervisor config (current)
├── docker-next/ # Next-generation Docker setup (in progress)
├── docs/ # User-facing documentation (markdown)
├── internal/ # All application code (288 .go files)
│ ├── app/ # Application-level utilities (metrics, ipynb sanitization)
│ ├── auth/ # Authentication providers
│ │ ├── github/ # GitHub OAuth
│ │ ├── ldap/ # LDAP/AD
│ │ ├── pam/ # PAM
│ │ └── smtp/ # SMTP auth
│ ├── authx/ # Auth domain extensions (token validation, etc.)
│ ├── avatar/ # Avatar fetching and storage
│ ├── conf/ # Configuration loading (INI-based, with testdata)
│ ├── context/ # HTTP request context; Macaron middleware
│ ├── cron/ # Scheduled background jobs
│ ├── cryptox/ # Cryptographic utilities
│ ├── database/ # Data access layer: models + store (with migrations, schemadoc)
│ │ ├── migrations/ # schema migration history
│ │ ├── schemadoc/ # auto-generated schema documentation
│ │ └── testdata/ # test fixtures including backup snapshots
│ ├── dbtest/ # Database test helpers (shared test infrastructure)
│ ├── dbx/ # Low-level database connection utilities
│ ├── email/ # Email composition and delivery
│ ├── errx/ # Error type utilities
│ ├── form/ # Request form structs (binding targets)
│ ├── gitx/ # Git operation utilities
│ ├── httplib/ # HTTP client utilities
│ ├── iox/ # I/O utilities
│ ├── lazyregexp/ # Lazily-compiled regular expressions
│ ├── lfsx/ # Git LFS utilities
│ ├── markup/ # Content rendering (Markdown, highlight)
│ ├── mocks/ # Test mock implementations
│ ├── netx/ # Network utilities
│ ├── osx/ # OS/filesystem utilities
│ ├── pathx/ # Path manipulation utilities
│ ├── process/ # OS process management (for git subprocess calls)
│ ├── repox/ # Repository-domain utilities
│ ├── route/ # HTTP handler functions (82 .go files total)
│ │ ├── admin/ # Admin UI handlers
│ │ ├── api/v1/ # REST API v1 handlers
│ │ ├── dev/ # Dev-mode template preview
│ │ ├── lfs/ # Git LFS protocol handlers
│ │ ├── org/ # Organization handlers
│ │ ├── repo/ # Repository handlers (61 files — largest subpackage)
│ │ └── user/ # User handlers
│ ├── semverx/ # Semver comparison utilities
│ ├── ssh/ # Built-in SSH server
│ ├── strx/ # String utilities
│ ├── sync/ # Synchronization primitives
│ ├── template/ # HTML template helper functions + syntax highlighting
│ ├── testx/ # General test utilities
│ ├── tool/ # Miscellaneous utilities
│ ├── urlx/ # URL utilities
│ └── userx/ # User-domain utilities
├── public/ # Static web assets (CSS, JS, images, plugins) — embedded
├── scripts/ # Service manager configs: systemd, launchd, supervisor, Windows
└── templates/ # HTML templates (Macaron renderer) — embeddedEntry points#
Single binary with multiple subcommands (urfave/cli v3):
| Command | File | Purpose |
|---|---|---|
gogs web | cmd/gogs/web.go | Start the full web server (HTTP/HTTPS/FCGI/Unix socket) |
gogs serv | cmd/gogs/serv.go | SSH git-serve hook (called by sshd for each git push/pull) |
gogs hook | cmd/gogs/hook.go | Git server-side hooks (pre-receive, post-receive, update) |
gogs admin | cmd/gogs/admin.go | Admin CLI utilities (create user, etc.) |
gogs import | cmd/gogs/import.go | Import repositories from local disk |
gogs backup | cmd/gogs/backup.go | Create a backup archive |
gogs restore | cmd/gogs/restore.go | Restore from a backup archive |
The web server and SSH server are both part of a single binary; gogs serv is invoked as an authorized_keys command by OpenSSH.
Package organization#
Internal packages: Everything lives under
internal/; no public packages exist. Key groupings:internal/database— the central data layer; contains all model types and store implementationsinternal/route/*— HTTP handler tree organized by domain (user, repo, org, admin, api)internal/conf— INI-file configuration with typed config structsinternal/context— Macaron middleware providing the*context.Contextrequest objectinternal/auth/*— Pluggable authentication backendsinternal/*x— A family of utility packages following anx-suffix naming convention (iox, strx, osx, urlx, errx, netx, pathx, repox, dbx, lfsx, gitx, cryptox, authx, semverx, userx)
Public packages (pkg/): None. This is a pure application.
Layering: Loosely layered but not strictly enforced:
cmd/→internal/route/*(HTTP handlers) →internal/database(data access) → DBinternal/contextacts as horizontal glue; most route handlers accept*context.Context- No formal service layer; route handlers interact with
internal/databasedirectly (thin-controller style) internal/appprovides cross-cutting application concerns (metrics, security)
Build system#
- Build tool:
task(Taskfile.yml) — a modern Make alternative - Key targets:
task build— compiles./cmd/gogsto.bin/gogswith ldflags for build time/commit and optional build tags (e.g.,TAGS="cert pam")task web— builds and starts the web servertask generate— runsgo generate ./...task generate-schemadoc— regenerates database schema documentationtask lint— runs linter
- Docker: Yes, multi-stage.
Dockerfileusesgolang:1.26-alpinebuilder stage runningtask build, then analpine:3.23runtime stage with s6 process supervisor. A separateDockerfile.nextanddocker-next/directory indicate a Docker setup migration in progress.
Notable structural decisions#
x-suffix utility package convention: Gogs has a distinctive pattern of naming utility packages with anxsuffix (iox, strx, osx, urlx, etc.) to avoid collisions with stdlib packages (os,io,strings). This naming is consistent across ~15 packages and makes the internal/stdlib boundary visually clear.Route registration in
cmd/gogs/web.go: The entire route tree (700+ lines) lives in the binary’s entry file rather than in a dedicated router file withininternal/route. This collocates the HTTP topology with the server startup logic but makesweb.goa very large file. All handler functions themselves are ininternal/route/*.No service layer: Route handlers call
internal/databasestore functions directly. There is no intermediate service/domain layer separating HTTP concerns from business logic. This keeps the structure flat but blurs concerns in handlers.Embedded assets (Go embed): Both
public/(static files) andtemplates/(HTML templates) are embedded into the binary viago:embed, allowing true single-binary deployment. Aconf.Server.LoadAssetsFromDiskflag exists for development to reload from disk without rebuilding.internal/databasedominance: With 61 source files and direct access from route handlers, the database package is the largest and most central package. It contains both model structs and store operations, acting as both a domain model and a repository layer.Dual Docker setup: The presence of both
docker/anddocker-next/signals an ongoing infrastructure migration. The.nextvariant likely represents a modernized Docker configuration that hasn’t replaced the original yet.