1 use std
::future
::Future
;
4 use anyhow
::{bail, Error}
;
6 use http
::request
::Parts
;
8 use hyper
::{Body, Method, StatusCode}
;
11 use proxmox
::try_block
;
12 use proxmox
::api
::RpcEnvironmentType
;
13 use proxmox
::tools
::fs
::CreateOptions
;
14 use proxmox
::api
::UserInformation
;
16 use proxmox_rest_server
::{daemon, AuthError, ApiConfig, RestServer, RestEnvironment, ServerAdapter}
;
18 use proxmox_backup
::server
::auth
::check_pbs_auth
;
19 use proxmox_backup
::auth_helpers
::*;
20 use proxmox_backup
::config
;
23 proxmox_backup
::tools
::setup_safe_path_env();
25 if let Err(err
) = pbs_runtime
::main(run()) {
26 eprintln
!("Error: {}", err
);
27 std
::process
::exit(-1);
31 struct ProxmoxBackupApiAdapter
;
33 impl ServerAdapter
for ProxmoxBackupApiAdapter
{
37 _env
: RestEnvironment
,
39 ) -> Pin
<Box
<dyn Future
<Output
= Response
<Body
>> + Send
>> {
42 let index
= "<center><h1>Proxmox Backup API Server</h1></center>";
45 .status(StatusCode
::OK
)
46 .header(hyper
::header
::CONTENT_TYPE
, "text/html")
54 headers
: &'a HeaderMap
,
56 ) -> Pin
<Box
<dyn Future
<Output
= Result
<(String
, Box
<dyn UserInformation
+ Sync
+ Send
>), AuthError
>> + Send
+ 'a
>> {
58 check_pbs_auth(headers
, method
).await
63 async
fn run() -> Result
<(), Error
> {
64 if let Err(err
) = syslog
::init(
65 syslog
::Facility
::LOG_DAEMON
,
66 log
::LevelFilter
::Info
,
67 Some("proxmox-backup-api")) {
68 bail
!("unable to inititialize syslog - {}", err
);
71 config
::create_configdir()?
;
73 config
::update_self_signed_cert(false)?
;
75 proxmox_backup
::server
::create_run_dir()?
;
77 proxmox_backup
::rrd
::create_rrdb_dir()?
;
78 proxmox_backup
::server
::jobstate
::create_jobstate_dir()?
;
79 proxmox_backup
::tape
::create_tape_status_dir()?
;
80 proxmox_backup
::tape
::create_drive_state_dir()?
;
81 proxmox_backup
::tape
::create_changer_state_dir()?
;
82 proxmox_backup
::tape
::create_drive_lock_dir()?
;
84 if let Err(err
) = generate_auth_key() {
85 bail
!("unable to generate auth key - {}", err
);
87 let _
= private_auth_key(); // load with lazy_static
89 if let Err(err
) = generate_csrf_key() {
90 bail
!("unable to generate csrf key - {}", err
);
92 let _
= csrf_secret(); // load with lazy_static
94 let mut config
= ApiConfig
::new(
96 &proxmox_backup
::api2
::ROUTER
,
97 RpcEnvironmentType
::PRIVILEGED
,
98 ProxmoxBackupApiAdapter
,
101 let backup_user
= pbs_config
::backup_user()?
;
102 let mut commando_sock
= proxmox_rest_server
::CommandSocket
::new(proxmox_rest_server
::our_ctrl_sock(), backup_user
.gid
);
104 let dir_opts
= CreateOptions
::new().owner(backup_user
.uid
).group(backup_user
.gid
);
105 let file_opts
= CreateOptions
::new().owner(backup_user
.uid
).group(backup_user
.gid
);
107 config
.enable_access_log(
108 pbs_buildcfg
::API_ACCESS_LOG_FN
,
109 Some(dir_opts
.clone()),
110 Some(file_opts
.clone()),
114 config
.enable_auth_log(
115 pbs_buildcfg
::API_AUTH_LOG_FN
,
116 Some(dir_opts
.clone()),
117 Some(file_opts
.clone()),
122 let rest_server
= RestServer
::new(config
);
123 proxmox_rest_server
::init_worker_tasks(pbs_buildcfg
::PROXMOX_BACKUP_LOG_DIR_M
!().into(), file_opts
.clone())?
;
125 // http server future:
126 let server
= daemon
::create_daemon(
127 ([127,0,0,1], 82).into(),
129 let incoming
= hyper
::server
::conn
::AddrIncoming
::from_listener(listener
)?
;
132 daemon
::systemd_notify(daemon
::SystemdNotify
::Ready
)?
;
134 hyper
::Server
::builder(incoming
)
136 .with_graceful_shutdown(proxmox_rest_server
::shutdown_future())
137 .map_err(Error
::from
)
143 proxmox_rest_server
::write_pid(pbs_buildcfg
::PROXMOX_BACKUP_API_PID_FN
)?
;
145 let init_result
: Result
<(), Error
> = try_block
!({
146 proxmox_rest_server
::register_task_control_commands(&mut commando_sock
)?
;
147 commando_sock
.spawn()?
;
148 proxmox_rest_server
::catch_shutdown_signal()?
;
149 proxmox_rest_server
::catch_reload_signal()?
;
153 if let Err(err
) = init_result
{
154 bail
!("unable to start daemon - {}", err
);
158 log
::info
!("server shutting down, waiting for active workers to complete");
159 proxmox_rest_server
::last_worker_future().await?
;
161 log
::info
!("done - exit server");