https_webserver/
https_webserver.rs

1use pass_tool::{
2    actions::{
3        action, command, create_dir_perm, delete_file, install_apt_packages, many, perm,
4        start_service, stop_service, write_file, write_file_perm,
5    },
6    checks::{
7        check, is_file, path_is_missing, service_is_inactive, stdout_contains_once, user_is_root,
8    },
9    instruction, run_cli_with_input, Playbook,
10};
11
12const ABOUT: &str = "Example installing nginx webserver with letsencrypt certificate.
13This playbook will:
14  - configure firewall (will allow ssh, http, https)
15  - enable letsencrypt certificates for domain
16  - configure nginx static website with https support";
17const HELP: &str = "For configuration you need to provide comma separated values of your email address (for letsencrypt registration) and your domain name, example:
18
19```
20apply your_email@domain.com,your_domain.com
21```";
22const NGINX_CONF: &str = include_str!("https_webserver_nginx.conf");
23const CERTBOT_RENEW: &str = include_str!("https_webserver_certbot-renew");
24const INDEX_HTML: &str = include_str!("https_webserver_index.html");
25
26fn main() {
27    run_cli_with_input(
28        |input| {
29            let input = String::from_utf8(input.to_vec()).or(Err(HELP.to_owned()))?;
30            let mut parts = input.split(',');
31            let [Some(email), Some(domain)] = [parts.next(), parts.next()] else {
32                return Err(HELP.to_owned());
33            };
34            let nginx_conf = NGINX_CONF
35                .split("{--domain--}")
36                .collect::<Vec<_>>()
37                .join(domain);
38            Ok(Playbook::new(
39                "Install and configure nginx with https",
40                ABOUT,
41                [
42                    user_is_root(),
43                    check(
44                        "Os is Ubuntu 20.04",
45                        stdout_contains_once(["lsb_release", "-a"], "Ubuntu 20.04"),
46                    ),
47                ],
48                [
49                    instruction(action(
50                        "Upgrade apt packages",
51                        many([
52                            command(["apt", "update", "-y"]),
53                            command(["apt", "upgrade", "-y"]),
54                        ]),
55                    )),
56                    instruction(install_apt_packages(["nginx", "certbot"])),
57                    instruction(action(
58                        "Configure firewall",
59                        many([
60                            command(["ufw", "allow", "ssh"]),
61                            command(["ufw", "allow", "http"]),
62                            command(["ufw", "allow", "https"]),
63                            command(["ufw", "default", "deny", "incoming"]),
64                            command(["ufw", "default", "allow", "outgoing"]),
65                        ]),
66                    ))
67                    .with_env(check(
68                        "Firewall is inactive",
69                        stdout_contains_once(["ufw", "status"], "Status: inactive"),
70                    )),
71                    instruction(action("Stop nginx", stop_service("nginx"))),
72                    instruction(action(
73                        "Request ssl certificate",
74                        command([
75                            "certbot",
76                            "certonly",
77                            "--standalone",
78                            "--agree-tos",
79                            "--no-eff-email",
80                            "-m",
81                            email,
82                            "-d",
83                            domain,
84                        ]),
85                    ))
86                    .with_env(check("Nginx is inactive", service_is_inactive("nginx")))
87                    .confirm(check(
88                        "Ssl certificate exists",
89                        is_file(format!("/etc/letsencrypt/live/{domain}/fullchain.pem")),
90                    )),
91                    instruction(action(
92                        "Enable certbot renew",
93                        write_file_perm(
94                            "/etc/cron.weekly/certbot-renew",
95                            CERTBOT_RENEW,
96                            perm(0o555, "root"),
97                        ),
98                    ))
99                    .confirm(check(
100                        "Certbot renew is enabled",
101                        is_file("/etc/cron.weekly/certbot-renew"),
102                    )),
103                    instruction(action(
104                        "Delete default nginx site",
105                        delete_file("/etc/nginx/sites-enabled/default"),
106                    ))
107                    .confirm(check(
108                        "Default nginx site deleted",
109                        path_is_missing("/etc/nginx/sites-enabled/default"),
110                    )),
111                    instruction(action(
112                        "Create pass demo site nginx configuration",
113                        write_file("/etc/nginx/sites-enabled/pass-demo", nginx_conf),
114                    ))
115                    .confirm(check(
116                        "Pass demo site nginx configuration is exists",
117                        is_file("/etc/nginx/sites-enabled/pass-demo"),
118                    )),
119                    instruction(action(
120                        "Create website files",
121                        many([
122                            create_dir_perm("/srv/pass-demo-site", perm(0o774, "www-data")),
123                            write_file_perm(
124                                "/srv/pass-demo-site/index.html",
125                                INDEX_HTML,
126                                perm(0o664, "www-data"),
127                            ),
128                        ]),
129                    )),
130                    instruction(action("Start nginx", start_service("nginx"))),
131                    instruction(action("Start firewall", start_service("ufw"))),
132                    instruction(action(
133                        "Enable firewall",
134                        command(["ufw", "--force", "enable"]),
135                    )),
136                ],
137            ))
138        },
139        HELP,
140        include_str!("https_webserver.rs"),
141    );
142}