CaddyDash是一个简洁轻量化的Caddy2 Web管理面板, 旨在于通过简单的网页操作配置和管理Caddy.

项目目前处在v0.0.x Pre-Alpha 阶段

项目特点及界面

  • 轻量化: 基于Touka框架与SQLite3构建, 高效的同时内存占用极低
  • 可移植: 来源于Go的跨平台能力, 使得本项目可以在多种架构上简单部署
  • 响应式: 前端采用响应式设计, 基于原生HTML CSS JS构建
  • 多语言: 前端提供多语言支持, 现有zh-CN, en, 后续可继续扩充
  • 容器化: 支持Docker容器化部署

响应式界面

反向代理配置界面

reverse_proxy

全局配置

global

部署

推荐使用Docker Compose部署, 安装目录以/root/data/docker_data/caddydash为例

  1. 创建并进入目录
1
2
mkdir -p /root/data/docker_data/caddydash
cd /root/data/docker_data/caddydash
  1. 创建docker-compose.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
version: '3.8'

services:
  caddydash:
    image: wjqserver/caddydash:latest
    container_name: caddydash
    network_mode: host
    volumes:
      - ./config:/data/caddy/config
      - ./config.d:/data/caddy/config.d
      - ./log:/data/caddy/log
      - ./db:/data/caddy/db
      - ./caddy_internal_data:/root/.local/share/caddy
    
    restart: unless-stopped
  1. 启动容器
1
docker compose up -d

项目架构

前端

本项目采用**多页面应用(MPA)**架构, 基于原生HTML5/CSS3/JavaScript构建; 采用响应式设计, 对移动端适配良好

响应式设计:

  • 可折叠侧边栏:在移动设备上滑入/滑出
  • 自适应布局:内容流式重排以适应小屏幕
  • 触控友好控件:适当大小的按钮和输入框
  • 优化导航:移动设备特定的菜单交互

前端支持i18n, 目前阶段基本完善, 目前存在zh-CNen可选

本项目开发阶段重心放在后端, 前端还需要更多打磨

后端

  • HTTP框架: 本项目后端HTTP框架使用团队自有Touka框架进行构建, 使得我们可以拥有较大的自由度
  • 数据库: 采用轻量级的SQLite3作为后端数据库, 同时使用modernc.org/sqlite作为数据库驱动, 无CGo以保证跨平台
  • 配置生成: Caddy的配置生成基于Go强大的模板引擎

站点配置生成

以下检出代码内容许可证参看 https://github.com/WJQSERVER-STUDIO/caddydash/blob/main/LICENSE

后端基于以下配置结构来处理json并将其编码为gob存入数据库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
type CaddyUniConfig struct {
	DomainConfig CaddyUniDomainConfig     `json:"domain_config"`
	Mode         string                   `json:"mode"`
	Upstream     CaddyUniUpstreamConfig   `json:"upstream_config"`
	FileServer   CaddyUniFileServerConfig `json:"file_server_config"`
	Headers      map[string][]string      `json:"headers"`
	Log          CaddyUniLogConfig        `json:"log_config"`
	ErrorPage    CaddyUniErrorPageConfig  `json:"error_page_config"`
	Encode       CaddyUniEncodeConfig     `json:"encode_config"`
	TLSSnippet   CaddyUniTLSSnippetConfig `json:"tls_snippet_config"`
}

type CaddyUniDomainConfig struct {
	Domain      string   `json:"domain"`
	MutiDomains bool     `json:"muti_domains"`
	Domains     []string `json:"domains"`
}

type CaddyUniUpstreamConfig struct {
	EnableUpStream  bool                `json:"enable_upstream"`
	UpStream        string              `json:"upstream"`
	MutiUpStreams   bool                `json:"muti_upstream"`
	UpStreams       []string            `json:"upstream_servers"`
	UpStreamHeaders map[string][]string `json:"upstream_headers"`
}

type CaddyUniFileServerConfig struct {
	EnableFileServer bool   `json:"enable_file_server"`
	FileDirPath      string `json:"file_dir_path"`
	EnableBrowser    bool   `json:"enable_browser"`
}

type CaddyUniLogConfig struct {
	EnableLog bool   `json:"enable_log"`
	LogDomain string `json:"log_domain"`
}

type CaddyUniErrorPageConfig struct {
	EnableErrorPage bool `json:"enable_error_page"`
}

type CaddyUniEncodeConfig struct {
	EnableEncode bool `json:"enable_encode"`
}

type CaddyUniTLSSnippetConfig struct {
	EnableSiteTLSSnippet bool `json:"enable_site_tls_snippet"`
}

同时使用以下模板结合配置渲染为具体的Caddy站点配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{{- if .DomainConfig.MutiDomains -}}
	{{- range $i, $domain := .DomainConfig.Domains -}}
		{{- if $i}} {{" "}}{{- end -}}
		{{- . -}}
	{{- end -}} {
{{- else -}}
	{{- .DomainConfig.Domain}} {
{{- end -}}

	{{- if .Upstream.EnableUpStream}}
	reverse_proxy {
		to{{if .Upstream.MutiUpStreams}}{{range .Upstream.UpStreams}} {{.}}{{end}}{{else}} {{.Upstream.UpStream}}{{end}}

		{{- range $key, $values := .Upstream.UpStreamHeaders}}
			{{- range $values}}
		header_up {{$key}} "{{.}}"
			{{- end}}
		{{- end}}
	}
	{{- else if .FileServer.EnableFileServer}}
	root * {{.FileServer.FileDirPath}}
	file_server{{if .FileServer.EnableBrowser}} browse{{end}}
	{{- end}}

	{{- range $key, $values := .Headers}}
		{{- range $values}}
	header {{$key}} "{{.}}"
		{{- end}}
	{{- end}}

	{{- if .Log.EnableLog}}
	import log {{.Log.LogDomain}}
	{{- end}}

	{{- if .ErrorPage.EnableErrorPage}}
	import error_page
	{{- end}}

	{{- if .Encode.EnableEncode}}
	import encode
	{{- end}}

	{{- if .TLSSnippet.EnableSiteTLSSnippet}}
	import tls
	{{- end}}
}

Caddy管理

我们使用一个goroutine来启动并管理Caddy实例, 这使得CaddyDash拥有较大的控制权, 并为后续扩展做好准备

HTTP框架

我们使用了团队自行开发实现的Touka框架, 这使得我们在一些特殊需求上可以有更好的解决方案

同时本项目使用了以下中间件

Record(访问日志)

Reco(异步日志库)

Sessions(用于鉴权) 移植自Gin Sessions

Compress(提供压缩支持)

CacheCtrl(配置缓存控制头)

许可证与贡献

本项目使用MPL 2.0许可证授权: https://github.com/WJQSERVER-STUDIO/caddydash/blob/main/LICENSE

欢迎各位贡献代码以帮助项目发展, 贡献代码的许可请参阅MPL 2.0的声明

项目状态

项目目前处在v0.0.x Pre-Alpha 阶段, 内部和外部API都有可能会存在较大变动, 当前品质不代表最终品质

目前存在较多功能预留, 需要后续进行实现

相关项目