2024-12-10 20:26:33 +01:00
{
config ,
lib ,
pkgs ,
. . .
} :
2021-05-17 21:19:12 -04:00
let
cfg = config . services . cloudflared ;
2025-02-18 17:08:30 +00:00
certificateFile = lib . mkOption {
type = with lib . types ; nullOr path ;
description = ''
2025-03-15 11:47:07 +00:00
Account certificate file , necessary to create , delete and manage tunnels . It can be obtained by running ` cloudflared login ` .
2025-02-18 17:08:30 +00:00
2025-03-15 11:47:07 +00:00
Note that this is * * necessary * * for a fully declarative set up , as routes can not otherwise be created outside of the Cloudflare interface .
See [ Cert . pem ] ( https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-terms/ #certpem) for information about the file, and [Tunnel permissions](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions/) for a comparison between the account certificate and the tunnel credentials file.
2025-02-18 17:08:30 +00:00
'' ;
default = null ;
} ;
2021-05-17 21:19:12 -04:00
originRequest = {
2024-08-28 21:19:03 +02:00
connectTimeout = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " 3 0 s " ;
2024-04-13 14:54:15 +02:00
description = ''
2024-04-10 21:12:51 -07:00
Timeout for establishing a new TCP connection to your origin server . This excludes the time taken to establish TLS , which is controlled by [ tlsTimeout ] ( https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/ #tlstimeout).
2021-05-17 21:19:12 -04:00
'' ;
} ;
2024-08-28 21:19:03 +02:00
tlsTimeout = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " 1 0 s " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Timeout for completing a TLS handshake to your origin server , if you have chosen to connect Tunnel to an HTTPS server .
'' ;
} ;
2024-08-28 21:19:03 +02:00
tcpKeepAlive = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " 3 0 s " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
The timeout after which a TCP keepalive packet is sent on a connection between Tunnel and the origin server .
'' ;
} ;
2024-08-28 21:19:03 +02:00
noHappyEyeballs = lib . mkOption {
type = with lib . types ; nullOr bool ;
2021-05-17 21:19:12 -04:00
default = null ;
example = false ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Disable the “ happy eyeballs ” algorithm for IPv4/IPv6 fallback if your local network has misconfigured one of the protocols .
'' ;
} ;
2024-08-28 21:19:03 +02:00
keepAliveConnections = lib . mkOption {
type = with lib . types ; nullOr int ;
2021-05-17 21:19:12 -04:00
default = null ;
example = 100 ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Maximum number of idle keepalive connections between Tunnel and your origin . This does not restrict the total number of concurrent connections .
'' ;
} ;
2024-08-28 21:19:03 +02:00
keepAliveTimeout = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " 1 m 3 0 s " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Timeout after which an idle keepalive connection can be discarded .
'' ;
} ;
2024-08-28 21:19:03 +02:00
httpHostHeader = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Sets the HTTP ` Host ` header on requests sent to the local service .
'' ;
} ;
2024-08-28 21:19:03 +02:00
originServerName = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Hostname that ` cloudflared ` should expect from your origin server certificate .
'' ;
} ;
2024-08-28 21:19:03 +02:00
caPool = lib . mkOption {
type = with lib . types ; nullOr ( either str path ) ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Path to the certificate authority ( CA ) for the certificate of your origin . This option should be used only if your certificate is not signed by Cloudflare .
'' ;
} ;
2024-08-28 21:19:03 +02:00
noTLSVerify = lib . mkOption {
type = with lib . types ; nullOr bool ;
2021-05-17 21:19:12 -04:00
default = null ;
example = false ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Disables TLS verification of the certificate presented by your origin . Will allow any certificate from the origin to be accepted .
'' ;
} ;
2024-08-28 21:19:03 +02:00
disableChunkedEncoding = lib . mkOption {
type = with lib . types ; nullOr bool ;
2021-05-17 21:19:12 -04:00
default = null ;
example = false ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Disables chunked transfer encoding . Useful if you are running a WSGI server .
'' ;
} ;
2024-08-28 21:19:03 +02:00
proxyAddress = lib . mkOption {
type = with lib . types ; nullOr str ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " 1 2 7 . 0 . 0 . 1 " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
` cloudflared ` starts a proxy server to translate HTTP traffic into TCP when proxying , for example , SSH or RDP . This configures the listen address for that proxy .
'' ;
} ;
2024-08-28 21:19:03 +02:00
proxyPort = lib . mkOption {
type = with lib . types ; nullOr int ;
2021-05-17 21:19:12 -04:00
default = null ;
example = 0 ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
` cloudflared ` starts a proxy server to translate HTTP traffic into TCP when proxying , for example , SSH or RDP . This configures the listen port for that proxy . If set to zero , an unused port will randomly be chosen .
'' ;
} ;
2024-08-28 21:19:03 +02:00
proxyType = lib . mkOption {
2024-12-10 20:26:33 +01:00
type =
with lib . types ;
nullOr ( enum [
" "
" s o c k s "
] ) ;
2021-05-17 21:19:12 -04:00
default = null ;
example = " " ;
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
` cloudflared ` starts a proxy server to translate HTTP traffic into TCP when proxying , for example , SSH or RDP . This configures what type of proxy will be started . Valid options are :
- ` " " ` for the regular proxy
2024-06-20 00:49:01 +08:00
- ` " s o c k s " ` for a SOCKS5 proxy . Refer to the [ tutorial on connecting through Cloudflare Access using kubectl ] ( https://developers.cloudflare.com/cloudflare-one/tutorials/kubectl/ ) for more information .
2021-05-17 21:19:12 -04:00
'' ;
} ;
} ;
in
{
2025-02-18 17:08:30 +00:00
imports = [
( lib . mkRemovedOptionModule
[
" s e r v i c e s "
" c l o u d f l a r e d "
" u s e r "
]
''
Cloudflared now uses a dynamic user , and this option no longer has any effect .
If the user is still necessary , please define it manually using users . users . cloudflared .
''
)
( lib . mkRemovedOptionModule
[
" s e r v i c e s "
" c l o u d f l a r e d "
" g r o u p "
]
''
Cloudflared now uses a dynamic user , and this option no longer has any effect .
If the group is still necessary , please define it manually using users . groups . cloudflared .
''
)
] ;
2021-05-17 21:19:12 -04:00
2025-02-18 17:08:30 +00:00
options . services . cloudflared = {
inherit certificateFile ;
2021-05-17 21:19:12 -04:00
2025-02-18 17:08:30 +00:00
enable = lib . mkEnableOption " C l o u d f l a r e T u n n e l c l i e n t d a e m o n ( f o r m e r l y A r g o T u n n e l ) " ;
2021-05-17 21:19:12 -04:00
2024-08-28 21:19:03 +02:00
package = lib . mkPackageOption pkgs " c l o u d f l a r e d " { } ;
2021-05-17 21:19:12 -04:00
2024-08-28 21:19:03 +02:00
tunnels = lib . mkOption {
2024-04-13 14:54:15 +02:00
description = ''
2021-05-17 21:19:12 -04:00
Cloudflare tunnels .
'' ;
2024-12-10 20:26:33 +01:00
type = lib . types . attrsOf (
lib . types . submodule (
{ name , . . . }:
{
options = {
2025-02-18 17:08:30 +00:00
inherit certificateFile originRequest ;
2024-12-10 20:26:33 +01:00
credentialsFile = lib . mkOption {
2025-02-18 17:08:30 +00:00
type = lib . types . path ;
2024-12-10 20:26:33 +01:00
description = ''
Credential file .
See [ Credentials file ] ( https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-terms/ #credentials-file).
'' ;
} ;
2021-05-17 21:19:12 -04:00
2024-12-10 20:26:33 +01:00
warp-routing = {
enabled = lib . mkOption {
type = with lib . types ; nullOr bool ;
2021-05-17 21:19:12 -04:00
default = null ;
2024-04-13 14:54:15 +02:00
description = ''
2024-12-10 20:26:33 +01:00
Enable warp routing .
2021-05-17 21:19:12 -04:00
2024-12-10 20:26:33 +01:00
See [ Connect from WARP to a private network on Cloudflare using Cloudflare Tunnel ] ( https://developers.cloudflare.com/cloudflare-one/tutorials/warp-to-tunnel/ ) .
2021-05-17 21:19:12 -04:00
'' ;
} ;
2024-12-10 20:26:33 +01:00
} ;
2021-05-17 21:19:12 -04:00
2024-12-10 20:26:33 +01:00
default = lib . mkOption {
type = lib . types . str ;
description = ''
Catch-all service if no ingress matches .
2021-05-17 21:19:12 -04:00
2024-12-10 20:26:33 +01:00
See ` service ` .
'' ;
example = " h t t p _ s t a t u s : 4 0 4 " ;
} ;
2021-05-17 21:19:12 -04:00
2024-12-10 20:26:33 +01:00
ingress = lib . mkOption {
type =
with lib . types ;
attrsOf (
either str (
submodule (
{ hostname , . . . }:
{
options = {
inherit originRequest ;
service = lib . mkOption {
type = with lib . types ; nullOr str ;
default = null ;
description = ''
Service to pass the traffic .
See [ Supported protocols ] ( https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/ #supported-protocols).
'' ;
example = " h t t p : / / l o c a l h o s t : 8 0 , t c p : / / l o c a l h o s t : 8 0 0 0 , u n i x : / h o m e / p r o d u c t i o n / e c h o . s o c k , h e l l o _ w o r l d o r h t t p _ s t a t u s : 4 0 4 " ;
} ;
path = lib . mkOption {
type = with lib . types ; nullOr str ;
default = null ;
description = ''
Path filter .
If not specified , all paths will be matched .
'' ;
example = " / * . ( j p g | p n g | c s s | j s ) " ;
} ;
} ;
}
)
)
) ;
default = { } ;
description = ''
Ingress rules .
See [ Ingress rules ] ( https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/ ) .
'' ;
example = {
" * . d o m a i n . c o m " = " h t t p : / / l o c a l h o s t : 8 0 " ;
" * . a n o t h e r o n e . c o m " = " h t t p : / / l o c a l h o s t : 8 0 " ;
} ;
2021-05-17 21:19:12 -04:00
} ;
} ;
2024-12-10 20:26:33 +01:00
}
)
) ;
2021-05-17 21:19:12 -04:00
default = { } ;
example = {
" 0 0 0 0 0 0 0 0 - 0 0 0 0 - 0 0 0 0 - 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 " = {
credentialsFile = " / t m p / t e s t " ;
ingress = {
" * . d o m a i n 1 . c o m " = {
service = " h t t p : / / l o c a l h o s t : 8 0 " ;
} ;
} ;
default = " h t t p _ s t a t u s : 4 0 4 " ;
} ;
} ;
} ;
} ;
2024-08-28 21:19:03 +02:00
config = lib . mkIf cfg . enable {
2024-12-10 20:26:33 +01:00
systemd . targets = lib . mapAttrs' (
name : tunnel :
lib . nameValuePair " c l o u d f l a r e d - t u n n e l - ${ name } " {
description = " C l o u d f l a r e t u n n e l ' ${ name } ' t a r g e t " ;
requires = [ " c l o u d f l a r e d - t u n n e l - ${ name } . s e r v i c e " ] ;
after = [ " c l o u d f l a r e d - t u n n e l - ${ name } . s e r v i c e " ] ;
unitConfig . StopWhenUnneeded = true ;
}
) config . services . cloudflared . tunnels ;
systemd . services = lib . mapAttrs' (
name : tunnel :
let
filterConfig = lib . attrsets . filterAttrsRecursive (
_ : v :
! builtins . elem v [
null
[ ]
{ }
]
) ;
filterIngressSet = lib . filterAttrs ( _ : v : builtins . typeOf v = = " s e t " ) ;
filterIngressStr = lib . filterAttrs ( _ : v : builtins . typeOf v = = " s t r i n g " ) ;
ingressesSet = filterIngressSet tunnel . ingress ;
ingressesStr = filterIngressStr tunnel . ingress ;
fullConfig = filterConfig {
tunnel = name ;
2025-02-18 17:08:30 +00:00
credentials-file = " / r u n / c r e d e n t i a l s / c l o u d f l a r e d - t u n n e l - ${ name } . s e r v i c e / c r e d e n t i a l s . j s o n " ;
2024-12-10 20:26:33 +01:00
warp-routing = filterConfig tunnel . warp-routing ;
originRequest = filterConfig tunnel . originRequest ;
ingress =
( map (
key :
{
hostname = key ;
}
// lib . getAttr key ( filterConfig ( filterConfig ingressesSet ) )
) ( lib . attrNames ingressesSet ) )
++ ( map ( key : {
hostname = key ;
service = lib . getAttr key ingressesStr ;
} ) ( lib . attrNames ingressesStr ) )
++ [ { service = tunnel . default ; } ] ;
} ;
2023-12-27 22:50:00 +01:00
2024-12-10 20:26:33 +01:00
mkConfigFile = pkgs . writeText " c l o u d f l a r e d . y m l " ( builtins . toJSON fullConfig ) ;
2025-02-18 17:08:30 +00:00
certFile = if ( tunnel . certificateFile != null ) then tunnel . certificateFile else cfg . certificateFile ;
2024-12-10 20:26:33 +01:00
in
2025-02-18 17:08:30 +00:00
lib . nameValuePair " c l o u d f l a r e d - t u n n e l - ${ name } " {
2024-12-10 20:26:33 +01:00
after = [
" n e t w o r k . t a r g e t "
" n e t w o r k - o n l i n e . t a r g e t "
] ;
wants = [
" n e t w o r k . t a r g e t "
" n e t w o r k - o n l i n e . t a r g e t "
] ;
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
serviceConfig = {
2025-02-18 17:08:30 +00:00
RuntimeDirectory = " c l o u d f l a r e d - t u n n e l - ${ name } " ;
RuntimeDirectoryMode = " 0 4 0 0 " ;
LoadCredential = [
" c r e d e n t i a l s . j s o n : ${ tunnel . credentialsFile } "
] ++ ( lib . optional ( certFile != null ) " c e r t . p e m : c e r t F i l e " ) ;
2024-12-10 20:26:33 +01:00
ExecStart = " ${ cfg . package } / b i n / c l o u d f l a r e d t u n n e l - - c o n f i g = ${ mkConfigFile } - - n o - a u t o u p d a t e r u n " ;
Restart = " o n - f a i l u r e " ;
2025-02-18 17:08:30 +00:00
DynamicUser = true ;
2024-12-10 20:26:33 +01:00
} ;
2021-05-17 21:19:12 -04:00
2025-02-18 17:08:30 +00:00
environment . TUNNEL_ORIGIN_CERT = lib . mkIf ( certFile != null ) '' % d / c e r t . p e m '' ;
}
) config . services . cloudflared . tunnels ;
2021-05-17 21:19:12 -04:00
} ;
2024-12-10 20:26:33 +01:00
meta . maintainers = with lib . maintainers ; [
bbigras
anpin
] ;
2021-05-17 21:19:12 -04:00
}