1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 17:14:08 +02:00

add mail service

This commit is contained in:
Robin Appelman 2024-06-12 14:45:09 +02:00
commit 1b734141e4
3 changed files with 139 additions and 29 deletions

View file

@ -6,7 +6,8 @@ Easy setup and management of Nextcloud test instances using docker
## What
`haze` provides an easy way to setup Nextcloud test instances with a choice of php version, database server, optional s3 or ldap setup and more.
`haze` provides an easy way to setup Nextcloud test instances with a choice of php version, database server, optional s3
or ldap setup and more.
## Setup
@ -53,28 +54,35 @@ See the [configuration section](#configuration) for more options.
haze start [database] [php-version] [services]
```
Where `database` is one of `sqlite`, `mysql`, `mariadb`, `pgsql` or `oracle` with an optional version (e.g. `pgsql:12`), defaults to `sqlite`.
And `php-version` is one of `8.1`, `8.2`, `8.3`, defaults to `8.1`. `7.3` and `7.4` and `8.0` are still supported but the docker images for those versions aren't being updated anymore so they might be missing some newer features.
Where `database` is one of `sqlite`, `mysql`, `mariadb`, `pgsql` or `oracle` with an optional version (e.g. `pgsql:12`),
defaults to `sqlite`.
And `php-version` is one of `8.1`, `8.2`, `8.3`, defaults to `8.1`. `7.3` and `7.4` and `8.0` are still supported but
the docker images for those versions aren't being updated anymore so they might be missing some newer features.
Each php version also comes with a `-dbg` variant that has php compiled in debug mode and can be used for debugging php itself with gdb.
Each php version also comes with a `-dbg` variant that has php compiled in debug mode and can be used for debugging php
itself with gdb.
Additionally, you can use the following options when starting an instance:
- `s3`: setup an S3 server and configure to Nextcloud to use it as primary storage
- `<path to app.tar.gz>`: by specifying the path to an app package this package will be extracted into the apps directory of the new instance (overwriting any existing app code). This can be used to quickly test a packaged app.
- `ldap`: setup an LDAP server
- `office`: setup a Nextcloud Office server
- `onlyoffice` setup an onlyoffice document server
- `push` setup [client push](https://github.com/nextcloud/notify_push)
- `smb`: setup a samba server for external storage use
- `dav`: setup a WebDAV server for external storage use
- `sftp`: setup a SFTP server for external storage use
- `kaspersky`: setup a kaspersky scan engine server in http mode. (Requires [manually setting up the image](https://github.com/icewind1991/kaspersky-docker))
- `s3`: setup an S3 server and configure to Nextcloud to use it as primary storage.
- `<path to app.tar.gz>`: by specifying the path to an app package this package will be extracted into the apps.
directory of the new instance (overwriting any existing app code). This can be used to quickly test a packaged app.
- `ldap`: setup an LDAP server.
- `office`: setup a Nextcloud Office server.
- `onlyoffice` setup an onlyoffice document server.
- `push` setup [client push](https://github.com/nextcloud/notify_push).
- `smb`: setup a samba server for external storage use.
- `dav`: setup a WebDAV server for external storage use.
- `sftp`: setup a SFTP server for external storage use.
- `kaspersky`: setup a kaspersky scan engine server in http mode. (
Requires [manually setting up the image](https://github.com/icewind1991/kaspersky-docker))
- `kaspersky-icap`: setup a kaspersky scan engine server in ICAP mode.
- `clamav-icap`: setup a clam av scanner in ICAP mode.
- `clamav-icap-tls`: setup a clam av scanner in ICAP mode with TLS encryption.
- `oc`: start an ownCloud instance in the same network.
- `imaginary`: start an Imaginary service and configure it for preview generation
- The name of any configured preset
- `imaginary`: start an Imaginary service and configure it for preview generation.
- `mail`: start an [smtp4dev](https://github.com/rnwood/smtp4dev) server and configure it the mail server.
- The name of any configured preset.
#### Run tests in a new instance
@ -104,7 +112,8 @@ haze clean
## Controlling running instances
The following commands run against the most recently started instance and allow optionally providing a `match` to select a specific instance by it's name.
The following commands run against the most recently started instance and allow optionally providing a `match` to select
a specific instance by it's name.
#### Open an instance
@ -178,13 +187,15 @@ haze [match] unpin
haze [match] env <cmd> [args]
```
Runs the provided command with `NEXTCLOUD_URL`, `DATABASE_URL` and `REDIS_URL` environment variables set for the matched instance.
Runs the provided command with `NEXTCLOUD_URL`, `DATABASE_URL` and `REDIS_URL` environment variables set for the matched
instance.
This is indented to run a local [push daemon](https://github.com/nextcloud/notify_push) against an instance.
## Federation
Multiple instances can reach each other by using their instance name as domain name to allow for testing federation between instances.
Multiple instances can reach each other by using their instance name as domain name to allow for testing federation
between instances.
Alternatively, you can setup the haze proxy and the proxied domains to get https support between instances.
## Proxy
@ -200,16 +211,22 @@ haze comes with a builtin reverse proxy to allow using a wildcard domain.
### Setup
- Set a DNS record for `*.haze.exmaple.com` and `haze.example.com` pointing to your development machine. (127.0.0.1 will not work)
- Set a DNS record for `*.haze.exmaple.com` and `haze.example.com` pointing to your development machine. (127.0.0.1 will
not work)
- Set the `proxy` configuration with your domain and desired listen endpoint
- Setup a service to run `haze proxy` in the background as your own user. A systemd user service is recommended.
- Configure your reverse proxy of choice to proxy `*.haze.example.com` and `haze.example.com` to the proxy's listen endpoint
- Configure your reverse proxy of choice to proxy `*.haze.example.com` and `haze.example.com` to the proxy's listen
endpoint
- (optional) acquire a wildcard ssl certificate for your domain and set your reverse proxy to use it.
This will be highly dependent on your DNS provider, [this](https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438) lists some DNS providers and supported ACME clients.
This will be highly dependent on your DNS
provider, [this](https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438)
lists some DNS providers and supported ACME clients.
### Usage
When the proxy is configured, generated urls for the instances will use a subdomain of the configured domain, e.g. the `rolling-bees` instance will be available at `rolling-bees.haze.example.com`. Additionally, `haze.example.com` will automatically point to the last created instance.
When the proxy is configured, generated urls for the instances will use a subdomain of the configured domain, e.g.
the `rolling-bees` instance will be available at `rolling-bees.haze.example.com`. Additionally, `haze.example.com` will
automatically point to the last created instance.
## Configuration

View file

@ -10,6 +10,7 @@ mod onlyoffice;
mod push;
mod sftp;
mod smb;
mod mail;
use crate::config::{HazeConfig, Preset};
pub use crate::service::clam::{ClamIcap, ClamIcapTls};
@ -31,6 +32,7 @@ use miette::{IntoDiagnostic, Report, Result, WrapErr};
use std::net::IpAddr;
use std::time::Duration;
use tokio::time::{sleep, timeout};
use crate::service::mail::Mail;
#[async_trait::async_trait]
#[enum_dispatch(Service)]
@ -183,6 +185,7 @@ pub enum Service {
ClamIcapTls(ClamIcapTls),
Oc(Oc),
Imaginary(Imaginary),
Mail(Mail),
Preset(PresetService),
}
@ -208,6 +211,7 @@ impl Service {
"clamav-icap-tls" => Some(vec![Service::ClamIcapTls(ClamIcapTls)]),
"clam-icap" => Some(vec![Service::ClamIcap(ClamIcap)]),
"clam-icap-tls" => Some(vec![Service::ClamIcapTls(ClamIcapTls)]),
"mail" => Some(vec![Service::Mail(Mail)]),
_ => presets
.iter()
.find_map(|preset| (preset.name == ty).then(|| PresetService(preset.name.clone())))

89
src/service/mail.rs Normal file
View file

@ -0,0 +1,89 @@
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::Result;
use bollard::container::{Config, CreateContainerOptions, NetworkingConfig};
use bollard::models::{EndpointSettings, HostConfig};
use bollard::Docker;
use maplit::hashmap;
use miette::IntoDiagnostic;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Mail;
#[async_trait::async_trait]
impl ServiceTrait for Mail {
fn name(&self) -> &str {
"mail"
}
async fn spawn(
&self,
docker: &Docker,
cloud_id: &str,
network: &str,
_config: &HazeConfig,
) -> Result<Option<String>> {
let image = "rnwood/smtp4dev";
pull_image(docker, image).await?;
let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default()
});
let config = Config {
image: Some(image),
host_config: Some(HostConfig {
network_mode: Some(network.to_string()),
..Default::default()
}),
labels: Some(hashmap! {
"haze-type" => self.name(),
"haze-cloud-id" => cloud_id
}),
networking_config: Some(NetworkingConfig {
endpoints_config: hashmap! {
network => EndpointSettings {
aliases: Some(vec![self.name().to_string()]),
..Default::default()
}
},
}),
..Default::default()
};
let id = docker
.create_container(options, config)
.await
.into_diagnostic()?
.id;
docker
.start_container::<String>(&id, None)
.await
.into_diagnostic()?;
Ok(Some(id))
}
fn container_name(&self, cloud_id: &str) -> Option<String> {
Some(format!("{}-mail", cloud_id))
}
// no need to wait for mail, as it won't be used until the user logs in
async fn is_healthy(&self, _docker: &Docker, _cloud_id: &str) -> Result<bool> {
Ok(true)
}
async fn post_setup(
&self,
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
Ok(vec![
"occ config:system:set mail_smtpmode --value smtp".into(),
"occ config:system:set mail_sendmailmode --value smtp".into(),
"occ config:system:set mail_domain --value haze".into(),
"occ config:system:set mail_smtphost --value mail".into(),
"occ config:system:set mail_smtpport --value 25".into(),
"occ user:setting admin settings email admin@haze".into(),
])
}
}