1use serde::{Deserialize, Serialize};
2
3use crate::SecretRef;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6pub struct TlsConfig {
7 pub mode: TlsMode,
8 #[serde(default)]
9 pub challenge: Option<AcmeChallenge>,
10 #[serde(default)]
11 pub provider: Option<TlsProvider>,
12 #[serde(default)]
13 pub account_secret: Option<SecretRef>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct DatabaseConfig {
18 #[serde(default = "default_database_driver")]
19 pub driver: DatabaseDriver,
20 #[serde(default = "default_database_url_secret")]
21 pub url: Option<SecretRef>,
22 #[serde(default = "default_database_schema")]
23 pub schema: String,
24 #[serde(default = "default_migrations_table")]
25 pub migrations_table: String,
26 #[serde(default = "default_min_database_connections")]
27 pub min_connections: u16,
28 #[serde(default = "default_max_database_connections")]
29 pub max_connections: u16,
30 #[serde(default = "default_statement_timeout_secs")]
31 pub statement_timeout_secs: u64,
32}
33
34impl Default for DatabaseConfig {
35 fn default() -> Self {
36 Self {
37 driver: default_database_driver(),
38 url: default_database_url_secret(),
39 schema: default_database_schema(),
40 migrations_table: default_migrations_table(),
41 min_connections: default_min_database_connections(),
42 max_connections: default_max_database_connections(),
43 statement_timeout_secs: default_statement_timeout_secs(),
44 }
45 }
46}
47
48#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
49#[serde(rename_all = "snake_case")]
50pub enum DatabaseDriver {
51 Postgres,
52}
53
54#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
55#[serde(rename_all = "kebab-case")]
56pub enum TlsMode {
57 External,
58 Acme,
59 CloudflareOrigin,
60 Manual,
61}
62
63#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
64pub enum AcmeChallenge {
65 #[serde(rename = "http-01")]
66 Http01,
67 #[serde(rename = "tls-alpn-01")]
68 TlsAlpn01,
69 #[serde(rename = "dns-01")]
70 Dns01,
71}
72
73#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
74#[serde(rename_all = "kebab-case")]
75pub enum TlsProvider {
76 CloudflareDns,
77 CloudflareOriginCa,
78 ManualImport,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
82pub struct StorageConfig {
83 pub default_class: StorageClass,
84 #[serde(default = "default_storage_deployment")]
85 pub deployment: StorageDeployment,
86 #[serde(default = "default_single_node_escape_hatch")]
87 pub single_node_escape_hatch: SingleNodeStorageMode,
88 #[serde(default)]
89 pub object_store: Option<ObjectStoreKind>,
90 pub local_root: String,
91 #[serde(default)]
92 pub object_store_secret: Option<SecretRef>,
93}
94
95#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
96#[serde(rename_all = "snake_case")]
97pub enum StorageDeployment {
98 Distributed,
99 SingleNode,
100}
101
102#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
103#[serde(rename_all = "snake_case")]
104pub enum SingleNodeStorageMode {
105 Disabled,
106 ExplicitSingleNode,
107}
108
109#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
110#[serde(rename_all = "snake_case")]
111pub enum StorageClass {
112 PublicAsset,
113 PublicUpload,
114 PrivateShared,
115 LocalOnlySensitive,
116}
117
118#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
119#[serde(rename_all = "snake_case")]
120pub enum ObjectStoreKind {
121 S3,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
125pub struct CacheConfig {
126 pub l1: CacheL1,
127 #[serde(default)]
128 pub l2: Option<DistributedCache>,
129}
130
131#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
132#[serde(rename_all = "snake_case")]
133pub enum CacheL1 {
134 Moka,
135}
136
137#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
138#[serde(rename_all = "snake_case")]
139pub enum DistributedCache {
140 Redis,
141 Valkey,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
145pub struct JobsConfig {
146 pub backend: JobBackend,
147 #[serde(default = "default_retry_limit")]
148 pub retry_limit: u32,
149}
150
151#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
152#[serde(rename_all = "snake_case")]
153pub enum JobBackend {
154 Redis,
155 Valkey,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
159pub struct ObservabilityConfig {
160 pub metrics: bool,
161 pub tracing: bool,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
165pub struct AssetsConfig {
166 pub publish_manifest: bool,
167 #[serde(default)]
168 pub cdn_base_url: Option<String>,
169}
170
171fn default_retry_limit() -> u32 {
172 5
173}
174
175fn default_database_driver() -> DatabaseDriver {
176 DatabaseDriver::Postgres
177}
178
179fn default_database_url_secret() -> Option<SecretRef> {
180 Some(SecretRef::Env {
181 var: "DATABASE_URL".to_string(),
182 })
183}
184
185fn default_database_schema() -> String {
186 "public".to_string()
187}
188
189fn default_migrations_table() -> String {
190 "_coil_migrations".to_string()
191}
192
193fn default_min_database_connections() -> u16 {
194 4
195}
196
197fn default_max_database_connections() -> u16 {
198 32
199}
200
201fn default_statement_timeout_secs() -> u64 {
202 30
203}
204
205fn default_storage_deployment() -> StorageDeployment {
206 StorageDeployment::Distributed
207}
208
209fn default_single_node_escape_hatch() -> SingleNodeStorageMode {
210 SingleNodeStorageMode::Disabled
211}