podbox/codegen/quadlet/
services.rs1use std::path::Path;
8
9use crate::config::Config;
10
11pub fn generate_build(config: &Config, containerfile_path: &Path) -> String {
13 let mut lines: Vec<String> = Vec::new();
14
15 lines.push("[Build]".into());
16 lines.push(format!(
17 "ImageTag=localhost/podbox-{}:latest",
18 config.image.name
19 ));
20 lines.push(format!("File={}", containerfile_path.to_string_lossy()));
21 lines.push(format!("Retry={}", config.image.pull_retry));
22 lines.push(format!("RetryDelay={}", config.image.pull_retry_delay));
23
24 lines.join("\n")
25}
26
27pub fn generate_socket(config: &Config) -> String {
29 let name = &config.container.name;
30 let host_service = format!("{name}-host.service");
31 let mut lines: Vec<String> = Vec::new();
32
33 lines.push("[Unit]".into());
34 lines.push(format!("Description=podbox host-guest socket -- {name}"));
35 lines.push(String::new());
36
37 lines.push("[Socket]".into());
38 lines.push(format!("ListenStream=%t/podbox/{name}.sock"));
39 lines.push(format!("Service={host_service}"));
40 lines.push("SocketMode=0600".into());
41 lines.push("DirectoryMode=0700".into());
42 lines.push("RuntimeDirectory=podbox".into());
43 lines.push("RuntimeDirectoryMode=0700".into());
44 lines.push("RuntimeDirectoryPreserve=yes".into());
48 lines.push(String::new());
49
50 lines.push("[Install]".into());
51 lines.push("WantedBy=sockets.target".into());
52
53 lines.join("\n")
54}
55
56pub fn generate_dbus_proxy_service(name: &str, config: &Config) -> Option<String> {
58 if !config.use_dbus_proxy() {
59 return None;
60 }
61
62 let mut args = vec![
63 "unix:path=%t/bus".to_string(),
64 format!("%t/podbox/{}-dbus.sock", name),
65 ];
66
67 args.push("--filter".into());
68
69 for service in &config.dbus_effective_talk() {
70 args.push(format!("--talk={service}"));
71 }
72 for rule in config.dbus_portal_calls() {
73 args.push(rule);
74 }
75 for service in &config.dbus.own {
76 args.push(format!("--own={service}"));
77 }
78
79 let exec_start = format!("/usr/bin/xdg-dbus-proxy {}", args.join(" "));
80
81 Some(format!(
82 r#"[Unit]
83Description=D-Bus Proxy for podbox container {name}
84PartOf={name}.service
85
86[Service]
87Type=simple
88ExecStart={exec_start}
89Restart=on-failure
90RestartSec=1s
91
92[Install]
93WantedBy={name}.service
94"#,
95 ))
96}
97
98pub fn generate_compositor_service(name: &str, config: &Config) -> Option<String> {
101 if !config.use_wayland_proxy() {
102 return None;
103 }
104 let podbox_bin = std::env::current_exe()
105 .map(|p| p.to_string_lossy().to_string())
106 .unwrap_or_else(|_| "/usr/local/bin/podbox".into());
107
108 Some(format!(
109 r#"[Unit]
110Description=Wayland Firewall Proxy for podbox container {name}
111PartOf={name}.service
112
113[Service]
114Type=simple
115ExecStart={podbox_bin} compositor {name}
116Restart=on-failure
117RestartSec=1s
118
119[Install]
120WantedBy={name}.service
121"#,
122 ))
123}
124
125pub fn generate_host_service(name: &str) -> String {
127 let podbox_bin = std::env::current_exe()
128 .map(|p| p.to_string_lossy().to_string())
129 .unwrap_or_else(|_| "/usr/local/bin/podbox".into());
130
131 format!(
132 r#"[Unit]
133Description=podbox host socket server -- {name}
134
135[Service]
136Type=simple
137ExecStart={podbox_bin} serve {name}
138Restart=on-failure
139RestartSec=2s
140
141[Install]
142WantedBy={name}.socket
143"#,
144 )
145}