Compare commits

..

5 commits

9 changed files with 180 additions and 5 deletions

25
.idea/jsonSchemas.xml Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JsonSchemaMappingsProjectConfiguration">
<state>
<map>
<entry key="docker-compose.yml">
<value>
<SchemaInfo>
<option name="name" value="docker-compose.yml" />
<option name="relativePathToSchema" value="https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" />
<option name="applicationDefined" value="true" />
<option name="patterns">
<list>
<Item>
<option name="path" value="compose.yml" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
</map>
</state>
</component>
</project>

View file

@ -13,7 +13,7 @@ categories = ["database"]
diesel = { version = "2.2.4", features = ["postgres", "uuid"] } diesel = { version = "2.2.4", features = ["postgres", "uuid"] }
diesel-async = { version = "0.5.1", features = ["postgres"] } diesel-async = { version = "0.5.1", features = ["postgres"] }
diesel_migrations = { version = "2.2.0", optional = true } diesel_migrations = { version = "2.2.0", optional = true }
log = "0.4.22" log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
mediatype = "0.19.18" mediatype = "0.19.18"
micronfig = { version = "0.3.0", optional = true } micronfig = { version = "0.3.0", optional = true }
mime = "0.3.17" mime = "0.3.17"

32
acrate_docker/Dockerfile Normal file
View file

@ -0,0 +1,32 @@
FROM rust AS base_builder
WORKDIR /usr/src/acrate
COPY --from=source ./acrate_database ./acrate_database
COPY --from=source ./acrate_nodeinfo ./acrate_nodeinfo
COPY --from=source ./acrate_rd ./acrate_rd
COPY --from=source ./acrate_rdserver ./acrate_rdserver
COPY --from=source ./Cargo.toml ./Cargo.toml
COPY --from=source ./Cargo.lock ./Cargo.lock
FROM rust:slim AS base_runner
RUN apt-get update
RUN apt-get upgrade --assume-yes
RUN apt-get install --assume-yes libpq5
WORKDIR /usr/local/bin
ENV RUST_LOG="warn"
FROM base_builder AS migrate_build
RUN cargo build --release --package=acrate_database --features=bin --bin=acrate_database_migrate
FROM base_runner AS migrate
COPY --from=migrate_build /usr/src/acrate/target/release/acrate_database_migrate /usr/local/bin/acrate_database_migrate
ENTRYPOINT ["acrate_database_migrate"]
ENV RUST_LOG="warn,acrate_database_migrate=info"
FROM base_builder AS rdserver_build
RUN cargo build --release --package=acrate_rdserver --bin=acrate_rdserver
FROM base_runner AS rdserver
COPY --from=rdserver_build /usr/src/acrate/target/release/acrate_rdserver /usr/local/bin/acrate_rdserver
ENTRYPOINT ["acrate_rdserver"]
HEALTHCHECK CMD ["curl", "http://127.0.0.1/.healthcheck"]
ENV RUST_LOG="warn,acrate_rdserver=info"

89
acrate_docker/compose.yml Normal file
View file

@ -0,0 +1,89 @@
# Full acrate stack, running on a single machine for experimental purposes
x-config:
ingress_config_dir: &ingress_config_dir "./config/caddy"
name: "acrate"
volumes:
ingress_data:
ingress_config:
postgres_data:
services:
# Public ingress node
ingress:
image: "caddy"
restart: "unless-stopped"
cap_add:
- "NET_ADMIN"
ports:
- protocol: "tcp"
target: 80
published: 80
- protocol: "tcp"
target: 443
published: 443
- protocol: "udp"
target: 443
published: 443
volumes:
- type: "volume"
source: "ingress_data"
target: "/data"
- type: "volume"
source: "ingress_config"
target: "/config"
- type: "bind"
source: *ingress_config_dir
target: "/etc/caddy"
# Main database
database:
image: "postgres"
restart: "unless-stopped"
environment:
# Make sure the password is the same for both client and server tools
POSTGRES_PASSWORD: &postgres_password "acrate"
PGUSER: "postgres"
PGPASS: *postgres_password
volumes:
- type: "volume"
source: "postgres_data"
target: "/var/lib/postgresql/data"
expose:
- 5432
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
# Migrations
migrate:
build:
dockerfile: "./Dockerfile"
additional_contexts:
- "source=.."
target: "migrate"
environment:
ACRATE_DATABASE_DATABASE_URL: &database_url "postgres:///postgres?host=database&user=postgres&password=acrate" # TODO: Split parameters off to their own envvars
depends_on:
database:
condition: "service_healthy"
# Resource descriptor server
rdserver:
build:
dockerfile: "./Dockerfile"
additional_contexts:
- "source=.."
target: "rdserver"
restart: "unless-stopped"
environment:
ACRATE_WEBFINGER_BIND_ADDRESS: "0.0.0.0:80"
ACRATE_WEBFINGER_DATABASE_URL: *database_url
expose:
- 80
depends_on:
database:
condition: "service_healthy"
migrate:
condition: "service_completed_successfully"

View file

@ -0,0 +1,16 @@
# replace with your HTTPS domain
:80 {
@rdserver {
path "/.well-known/webfinger"
path "/.well-known/host-meta"
path "/.well-known/host-meta.xml"
path "/.well-known/host-meta.json"
}
reverse_proxy @rdserver {
to "http://rdserver"
health_uri "/.healthcheck"
health_status "204"
}
}

View file

@ -11,7 +11,7 @@ categories = ["web-programming"]
[dependencies] [dependencies]
acrate_rd = { path = "../acrate_rd" } acrate_rd = { path = "../acrate_rd" }
log = "0.4.22" log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
mediatype = { version = "0.19.18", features = ["serde"] } mediatype = { version = "0.19.18", features = ["serde"] }
reqwest = { version = "0.12.9", features = ["json", "stream"] } reqwest = { version = "0.12.9", features = ["json", "stream"] }
serde = { version = "1.0.214", features = ["derive"] } serde = { version = "1.0.214", features = ["derive"] }

View file

@ -15,7 +15,7 @@ acrate_rd = { path = "../acrate_rd" }
anyhow = "1.0.93" anyhow = "1.0.93"
axum = { version = "0.7.7", features = ["macros"] } axum = { version = "0.7.7", features = ["macros"] }
axum-extra = { version = "0.9.4", features = ["query"] } axum-extra = { version = "0.9.4", features = ["query"] }
log = "0.4.22" log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
micronfig = "0.3.0" micronfig = "0.3.0"
minijinja = "2.5.0" minijinja = "2.5.0"
pretty_env_logger = "0.5.0" pretty_env_logger = "0.5.0"

View file

@ -21,6 +21,7 @@ async fn main() -> anyhow::Result<std::convert::Infallible> {
log::trace!("Creating Axum router..."); log::trace!("Creating Axum router...");
let app = axum::Router::new() let app = axum::Router::new()
.route("/*path", axum::routing::get(route::webfinger_handler)) .route("/*path", axum::routing::get(route::webfinger_handler))
.route("/.healthcheck", axum::routing::get(route::healthcheck_handler))
.layer(Extension(Arc::new(mj))); .layer(Extension(Arc::new(mj)));
log::trace!("Axum router created successfully!"); log::trace!("Axum router created successfully!");
@ -31,7 +32,7 @@ async fn main() -> anyhow::Result<std::convert::Infallible> {
.context("failed to bind listener to address")?; .context("failed to bind listener to address")?;
log::trace!("Tokio listener bound to: {bind_address}"); log::trace!("Tokio listener bound to: {bind_address}");
log::debug!("Starting server..."); log::info!("Starting server...");
axum::serve(listener, app) axum::serve(listener, app)
.await .await
.context("server exited with error")?; .context("server exited with error")?;

View file

@ -13,6 +13,18 @@ use acrate_rd::jrd::ResourceDescriptorLinkJRD;
use acrate_rd::xrd::{ResourceDescriptorLinkXRD, ResourceDescriptorPropertyXRD, ResourceDescriptorTitleXRD}; use acrate_rd::xrd::{ResourceDescriptorLinkXRD, ResourceDescriptorPropertyXRD, ResourceDescriptorTitleXRD};
use crate::config; use crate::config;
pub async fn healthcheck_handler() -> Result<StatusCode, StatusCode> {
log::debug!("Handling an healthcheck request!");
log::trace!("Making sure the database is up...");
let _conn = AsyncPgConnection::establish(config::ACRATE_WEBFINGER_DATABASE_URL())
.await
.map_err(|_| StatusCode::BAD_GATEWAY)?;
log::trace!("Healthcheck successful! Everything's fine!");
Ok(StatusCode::NO_CONTENT)
}
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct WebfingerQuery { pub struct WebfingerQuery {
pub resource: Option<String>, pub resource: Option<String>,
@ -27,7 +39,7 @@ pub async fn webfinger_handler(
headers: HeaderMap, headers: HeaderMap,
Extension(mj): Extension<Arc<minijinja::Environment<'static>>>, Extension(mj): Extension<Arc<minijinja::Environment<'static>>>,
) -> Result<Response<String>, StatusCode> { ) -> Result<Response<String>, StatusCode> {
log::info!("Handling a WebFinger request!"); log::debug!("Handling a WebFinger request!");
let resource = resource.unwrap_or_else(|| "".to_string()); let resource = resource.unwrap_or_else(|| "".to_string());
log::debug!("Resource is: {resource:#?}"); log::debug!("Resource is: {resource:#?}");