fixeria has uploaded this change for review.

View Change

doc/manuals: add overview, document running and configuration

Change-Id: I4ceca069866d7191ef2b153af95a20cb522bffeb
Related: OS#6671
---
M README.md
A doc/manuals/Makefile
A doc/manuals/chapters/configuration.adoc
A doc/manuals/chapters/overview.adoc
A doc/manuals/chapters/running.adoc
A doc/manuals/osmo-s1gw-usermanual-docinfo.xml
A doc/manuals/osmo-s1gw-usermanual.adoc
7 files changed, 730 insertions(+), 38 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/64/42364/1
diff --git a/README.md b/README.md
index 5ff4589..d6a5299 100644
--- a/README.md
+++ b/README.md
@@ -54,8 +54,10 @@
Documentation
-------------

-Once the project reaches a usable milestone, we will be working on a
-user manual. Stay tuned.
+The user manual source is in [`doc/manuals/`](doc/manuals/). It covers
+installation, configuration, metrics, the REST API, and the interactive CLI.
+A pre-built PDF is published on the
+[Osmocom documentation server](https://ftp.osmocom.org/docs/osmo-s1gw).


Contributing
@@ -113,54 +115,39 @@
Installation
------------

-OsmoS1GW is built for common versions of Debian, Ubuntu and other distributions as a part of
-the [Osmocom binary packages](https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_Packages).
-If you're not doing development, it is suggested to simply use those binary packages, rather
-than building from source. Otherwise, you can invoke the `install` target:
+Osmocom provides binary packages for common Debian and Ubuntu releases via
+the [Osmocom binary package feed](https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_Packages).
+Both a stable feed (tracking the latest release) and a nightly feed are
+available. If you are not doing development, using the binary packages is
+the recommended approach.
+
+To build and install from source:

```
+$ make
$ sudo make install
```

-This will install the following:
+`make install` deploys a complete ERTS release together with a convenience
+wrapper script and the interactive CLI tool:

-* `/usr/lib/osmo-s1gw` - complete OTP release package
-* `/usr/bin/osmo-s1gw` - convenience script for running `osmo-s1gw`
-* `/usr/bin/osmo-s1gw-cli` - interactive CLI for `osmo-s1gw`
-* `/lib/systemd/system/osmo-s1gw.service` - systemd unit file
-* `/etc/osmocom/osmo-s1gw.config` - the configuration file
+* `/usr/lib/osmo-s1gw` — complete OTP/ERTS release package
+* `/usr/bin/osmo-s1gw` — bootstrap script for starting the release
+* `/usr/bin/osmo-s1gw-cli` — interactive CLI tool
+* `/lib/systemd/system/osmo-s1gw.service` — systemd unit file
+* `/etc/osmocom/osmo-s1gw.config` — default configuration file

-The installation paths can be adjusted using `DESTDIR`, `LIBDIR`, `BINDIR`,
-`CONFDIR`, and `SYSTEMDUNITDIR` variables.
+Installation paths can be adjusted with `DESTDIR`, `LIBDIR`, `BINDIR`,
+`CONFDIR`, and `SYSTEMDUNITDIR`. See the user manual for full details.


Configuration
-------------

-The default configuration can be found in
-[config/sys.config](config/sys.config).
-
-The existing parameters can be represented as follows:
-
-```
- eNB S1GW
-+-----+ +----------------+
-| ... | --> | s1gw_bind_addr | MME
-+-----+ +----------------+ +-----------------+
- | mme_loc_addr | --> | mme_rem_addr |
- +----------------+ +-----------------+
-```
-
-* `s1gw_bind_addr` - S1GW bind address for incoming eNB connections
-* `mme_loc_addr` - local address for outgoing connections to the MME
-* `mme_rem_addr` - remote address for outgoing connections to the MME
-
-Logging can be configured in the `kernel` section:
-
-* `{logger_level, info}` - logging level (one of `emergency | alert |
- critical | error | warning | notice |
- info | debug`)
-* `#{formatter => { ... }` - logging formatting configuration
+The default configuration file is [`config/sys.config`](config/sys.config).
+For a full description of all available configuration parameters, see the
+Configuration chapter in the user manual
+([`doc/manuals/chapters/configuration.adoc`](doc/manuals/chapters/configuration.adoc)).


REST interface
diff --git a/doc/manuals/Makefile b/doc/manuals/Makefile
new file mode 100644
index 0000000..b56e51d
--- /dev/null
+++ b/doc/manuals/Makefile
@@ -0,0 +1,16 @@
+OSMO_GSM_MANUALS_DIR ?= $(shell pkg-config osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)
+ifeq ($(OSMO_GSM_MANUALS_DIR),)
+$(error "osmo-gsm-manuals not found via pkg-config. Please install it.")
+endif
+
+# Without autotools, srcdir must be set explicitly so that Makefile.asciidoc.inc
+# can resolve {srcdir} in AsciiDoc include directives correctly.
+srcdir ?= $(CURDIR)
+
+ASCIIDOC = osmo-s1gw-usermanual.adoc
+include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
+
+osmo-s1gw-usermanual.pdf: $(wildcard chapters/*.adoc)
+
+OSMO_REPOSITORY = osmo-s1gw
+include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
new file mode 100644
index 0000000..53e23e5
--- /dev/null
+++ b/doc/manuals/chapters/configuration.adoc
@@ -0,0 +1,304 @@
+[[configuration]]
+== Configuration
+
+OsmoS1GW is configured through an Erlang/OTP system configuration file.
+By default this file is `config/sys.config` in the source tree, or
+`/etc/osmocom/osmo-s1gw.config` after installation. A different path
+can be supplied at start time via the `-c` option of the `osmo-s1gw`
+bootstrap script (see <<running_bootstrap_script>>) or via the `CONFIG`
+variable when using the project Makefile (see <<running_building_make_targets>>).
+
+The file uses Erlang term syntax. The top level is a list of
+`{ApplicationName, [{Key, Value}, ...]}` tuples. OsmoS1GW-specific
+parameters live under the `osmo_s1gw` application key. Kernel
+parameters (logging) live under the standard `kernel` key, and metrics
+reporting parameters under the `exometer_core` key.
+
+[[config_sctp_server]]
+=== `sctp_server` — eNB-Facing SCTP Listener
+
+This section controls the SCTP socket on which OsmoS1GW listens for
+incoming connections from eNodeBs.
+
+----
+{sctp_server, #{
+ laddr => "127.0.1.1", %% local bind address
+ lport => 36412, %% local bind port (S1AP standard port)
+ sockopts => #{ } %% optional socket options (see below)
+}}
+----
+
+`laddr`::
+ IP address to bind to. Accepts a string in dotted-decimal (IPv4) or
+ colon-separated (IPv6) notation, or the atom `any` to bind to all
+ interfaces. Default: `"127.0.1.1"`.
+
+`lport`::
+ TCP/SCTP port to listen on. Default: `36412` (the IANA-assigned S1AP
+ port).
+
+`sockopts`::
+ An optional map of additional SCTP socket options:
++
+[options="header",cols="20,60,20"]
+|===
+| Option | Description | Default
+| `recbuf` | Receive buffer size in bytes | `65536`
+| `sndbuf` | Send buffer size in bytes | `65536`
+| `nodelay` | Disable Nagle algorithm (`true` to disable) | `true`
+|===
+
+[[config_mme_pool]]
+=== `mme_pool` — MME Pool Configuration
+
+The `mme_pool` key defines the list of MMEs that OsmoS1GW may connect to
+on behalf of connecting eNBs. This is the recommended way to configure
+MME connectivity; it supports multiple MMEs and TAC-based selection.
+
+----
+{mme_pool, [
+ #{
+ name => "mme0", %% unique name (required)
+ raddr => "192.168.2.10", %% MME IP address (required)
+ rport => 36412, %% MME SCTP port (default: 36412)
+ laddr => any, %% local bind address (default: any)
+ tac_list => [] %% allowed TACs (default: [] = all)
+ },
+ #{
+ name => "mme1",
+ raddr => "192.168.2.20",
+ tac_list => [100, 101, 102]
+ }
+]}
+----
+
+Each entry in the list is a map with the following fields:
+
+`name`::
+ A unique, human-readable string identifying this MME in log messages,
+ the REST API, and per-MME metrics. Required.
+
+`raddr`::
+ The remote IP address of the MME. Required.
+
+`rport`::
+ The remote SCTP port of the MME. Default: `36412`.
+
+`laddr`::
+ The local IP address to bind to when connecting to this MME. Accepts
+ a string or the atom `any`. Default: `any`.
+
+`tac_list`::
+ A list of Tracking Area Codes (TACs) that this MME is willing to serve.
+ When an eNB connects and sends its S1 Setup Request, OsmoS1GW filters
+ the pool to MMEs whose `tac_list` is a superset of the eNB's
+ advertised TACs. An empty list means the MME accepts all TACs.
+ Default: `[]`.
+
+MMEs can also be added and removed at run time via the REST API without
+restarting OsmoS1GW (see <<rest_mme>>).
+
+NOTE: The `mme_pool` key is mutually exclusive with the deprecated
+`sctp_client` key described in the next section. If `mme_pool` is
+present, keys `laddr`, `raddr`, and `rport` from the `sctp_client`
+block are ignored.
+
+[[config_sctp_client]]
+=== `sctp_client` — Single MME (Deprecated)
+
+Prior to the introduction of MME pooling, the outbound MME connection was
+configured via the `sctp_client` section:
+
+----
+{sctp_client, #{
+ laddr => "127.0.2.1", %% local bind address
+ raddr => "127.0.2.10", %% MME IP address
+ rport => 36412, %% MME SCTP port
+ sockopts => #{ } %% optional socket options (same as sctp_server)
+}}
+----
+
+When OsmoS1GW starts and finds no `mme_pool` key in the configuration,
+it automatically creates a single `"default"` MME pool entry from the
+`sctp_client` parameters and logs a deprecation warning. This allows
+existing single-MME deployments to continue working without changes, but
+migration to `mme_pool` is strongly recommended.
+
+NOTE: The socket options (`sockopts`) from the `sctp_client` section are
+still used for the outbound SCTP socket regardless of whether `mme_pool`
+or `sctp_client` is used for MME addressing.
+
+[[config_pfcp]]
+=== PFCP — User Plane Function
+
+These parameters control the PFCP session between OsmoS1GW and the UPF.
+
+----
+{pfcp_loc_addr, "127.0.1.1"}, %% local address for PFCP (UDP)
+{pfcp_rem_addr, "127.0.1.2"}, %% remote address of the UPF
+
+%% Optional Network Instance IEs:
+%% {pfcp_net_inst_core, "core-side"},
+%% {pfcp_net_inst_access, "radio-side"}
+----
+
+`pfcp_loc_addr`::
+ Local IP address on which OsmoS1GW listens for PFCP messages from the
+ UPF. Default: `"127.0.1.1"`.
+
+`pfcp_rem_addr`::
+ Remote IP address of the UPF. Default: `"127.0.1.2"`.
+
+`pfcp_net_inst_core`::
+ Value for the PFCP Network Instance IE on the core-network side of each
+ GTP-U session. Omit if the UPF does not require Network Instance IEs.
+
+`pfcp_net_inst_access`::
+ Value for the PFCP Network Instance IE on the radio-access side of each
+ GTP-U session. Omit if the UPF does not require Network Instance IEs.
+
+[[config_gtpu_kpi]]
+=== GTP-U KPI Reporting (Optional)
+
+OsmoS1GW can optionally poll nftables counters to derive per-eNB GTP-U
+traffic statistics and report them as exometer metrics. This feature
+requires a matching nftables ruleset.
+
+----
+%% {gtpu_kpi_enable, true},
+%% {gtpu_kpi_table_name, "osmo-s1gw"},
+%% {gtpu_kpi_ul_addr, s1ap},
+%% {gtpu_kpi_dl_addr, s1ap},
+%% {gtpu_kpi_interval, 3000}
+----
+
+`gtpu_kpi_enable`::
+ Set to `true` to enable the GTP-U KPI module. Default: `false`.
+
+`gtpu_kpi_table_name`::
+ The nftables table name to read counters from.
+ Default: `"osmo-s1gw"`.
+
+`gtpu_kpi_ul_addr`::
+ Source of the uplink GTP-U address used to match nftables counters.
+ `s1ap` means learn the address from S1AP signalling; `sctp` means use
+ the eNB's SCTP source address. Default: `s1ap`.
+
+`gtpu_kpi_dl_addr`::
+ Source of the downlink GTP-U address. Same options as `gtpu_kpi_ul_addr`.
+ Default: `s1ap`.
+
+`gtpu_kpi_interval`::
+ How often (in milliseconds) to poll the nftables counters.
+ Default: `3000`.
+
+[[config_rest]]
+=== REST Interface
+
+----
+%% {rest_srv_port, 8080},
+%% {rest_srv_swagger_ui, true}
+----
+
+`rest_srv_port`::
+ TCP port on which the HTTP REST server listens. Default: `8080`.
+
+`rest_srv_swagger_ui`::
+ Whether to serve the Swagger UI at `http://host:rest_srv_port/swagger`.
+ Default: `true`.
+
+[[config_kernel]]
+=== `kernel` — Logging
+
+OsmoS1GW uses the standard Erlang/OTP `logger` framework. The `kernel`
+application section controls log levels and handlers. See
+<<running_logging>> for a description of the log handlers configured by
+default.
+
+----
+{kernel, [
+ {logger_level, debug},
+ {logger, [
+ {handler, gsmtap, logger_gsmtap_h,
+ #{level => debug,
+ config => #{rem_addr => "127.0.0.1",
+ app_name => "OsmoS1GW"}}},
+ {handler, default, logger_std_h,
+ #{level => info,
+ formatter => {logger_color_formatter, #{...}}}}
+ ]}
+]}
+----
+
+`logger_level`::
+ The global minimum log level. Log records below this level are
+ discarded before reaching any handler. Common values: `debug`,
+ `info`, `notice`, `warning`, `error`.
+
+For each handler in the `logger` list:
+
+`level`::
+ Handler-specific minimum log level. Can be set independently per
+ handler to, for example, send only `warning` and above to the console
+ while sending all `debug` output over GSMTAP.
+
+`gsmtap` handler (`logger_gsmtap_h`)::
+ Sends log messages as GSMTAP frames over UDP.
++
+`rem_addr`::: Destination IP address. Default: `"127.0.0.1"`.
+`app_name`::: Application name tag embedded in each GSMTAP frame.
+
+`default` handler (`logger_std_h`)::
+ Writes log lines to standard output. When OsmoS1GW runs under systemd
+ this output is captured by the journal.
+
+[[config_exometer]]
+=== `exometer_core` — Metrics and StatsD Reporting
+
+OsmoS1GW uses the https://github.com/Feuerlabs/exometer_core[exometer_core]
+library for internal metrics (counters and gauges). The `exometer_core`
+section configures reporters — processes that periodically push metric
+values to an external destination.
+
+The default configuration reports all counters and gauges to a StatsD
+server:
+
+----
+{exometer_core, [
+ {report, [
+ {reporters, [
+ {exometer_report_statsd, [
+ {hostname, "127.0.4.10"},
+ {port, 8125},
+ {prefix, "s1gw"},
+ {type_map, []}
+ ]}
+ ]},
+ {subscribers, [
+ {select, {[{ {['_'|'_'], counter, '_'}, [], ['$_']}],
+ exometer_report_statsd, value, 1000, true,
+ [{report_type, counter}]}},
+ {select, {[{ {['_'|'_'], gauge, '_'}, [], ['$_']}],
+ exometer_report_statsd, value, 1000, true,
+ [{report_type, gauge}]}}
+ ]}
+ ]}
+]}
+----
+
+`hostname`::
+ IP address or hostname of the StatsD server.
+
+`port`::
+ UDP port of the StatsD server. Default: `8125`.
+
+`prefix`::
+ String prepended to all metric names as reported to StatsD.
+ Default: `"s1gw"`.
+
+The `subscribers` list uses exometer's `select` mechanism to
+automatically subscribe all counters and gauges to the StatsD reporter
+with a reporting interval of 1000 ms. To disable StatsD reporting,
+comment out or remove the `exometer_report_statsd` reporter entry.
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/chapters/overview.adoc b/doc/manuals/chapters/overview.adoc
new file mode 100644
index 0000000..d8248ca
--- /dev/null
+++ b/doc/manuals/chapters/overview.adoc
@@ -0,0 +1,121 @@
+[[overview]]
+== Overview
+
+[[about]]
+=== About OsmoS1GW
+
+OsmoS1GW is an S1 Gateway for LTE (4G) networks, developed by
+https://www.sysmocom.de/[sysmocom]. It acts as a transparent proxy
+between eNodeBs (eNBs, i.e. radio base stations) and one or more MMEs
+(Mobility Management Entities), relaying S1AP signalling over SCTP/IP in
+both directions.
+
+In addition to S1AP proxying, OsmoS1GW manages GTP-U data plane tunnels
+(E-RABs / EPS bearers) by communicating with a co-located UPF (User
+Plane Function) via PFCP. OsmoS1GW does not carry GTP-U traffic itself:
+GTP-U flows directly between the eNB and the UPF (access side), and
+between the UPF and the S-GW of the core network (core side). OsmoS1GW
+only instructs the UPF — via PFCP Session Establishment, Modification,
+and Deletion procedures — to create, update, or tear down the
+corresponding forwarding rules. It also rewrites the GTP-U TEID and
+Transport Layer Address (TLA) IEs inside S1AP messages so that eNBs send
+their GTP-U traffic to the UPF rather than directly to the core network.
+
+[[architecture]]
+=== Architecture
+
+The following diagram shows the high-level data flow through OsmoS1GW:
+
+----
+ S1AP/SCTP S1AP/SCTP
+eNB <----------> S1GW <----------> MME (core)
+ ^ ^
+ | |
+ | GTP-U | PFCP
+ | |
+ | GTP-U V GTP-U
+ +-------------> UPF <-----------> S-GW (core)
+----
+
+All S1AP messages are inspected by the gateway. Most are forwarded
+unchanged; those that carry GTP-U endpoint information (E-RAB Setup,
+Modify, Release, Initial Context Setup, etc.) are rewritten so that the
+UPF's TLA/TEID is substituted for the core network's endpoint before
+forwarding to the eNB. GTP-U traffic itself never passes through
+OsmoS1GW — it flows directly between the eNB and the UPF, and between
+the UPF and the S-GW.
+
+Internally, OsmoS1GW is structured as a set of Erlang/OTP processes:
+
+* *`sctp_server`* — Listens for incoming eNB SCTP connections and spawns
+ one `enb_proxy` instance per connection.
+* *`enb_proxy`* — One instance per connected eNB. Manages the outbound
+ SCTP connection to the selected MME and drives the S1 Setup handshake.
+ Implements MME pooling and retry logic.
+* *`s1ap_proxy`* — Paired with each `enb_proxy`. Inspects S1AP PDUs in
+ both directions and manages per-UE `erab_fsm` instances.
+* *`erab_fsm`* — One instance per active E-RAB. Exchanges PFCP Session
+ Establishment/Modification/Deletion messages with the UPF and rewrites
+ GTP-U F-TEID IEs in S1AP messages.
+* *`pfcp_peer`* — Manages the PFCP association with the UPF (UDP-based),
+ including periodic heartbeat and SEID allocation.
+* *`mme_registry`* — Manages the pool of known MMEs. MMEs can be
+ provisioned statically via the configuration file or dynamically via
+ the REST API.
+* *`enb_registry`* — Tracks all active eNB connections and their state.
+ Queryable via the REST API.
+* *`rest_server`* — OpenAPI-based HTTP REST interface for monitoring and
+ management.
+
+[[use_cases]]
+=== Use Cases
+
+[[use_case_isolated_networks]]
+==== Separated Core and Access Networks
+
+A common deployment scenario in private or industrial LTE networks is one
+where the core network (EPC) and the radio access network (RAN) reside in
+strictly separated IP domains with no direct routing between them — for
+example, a dedicated operations network for eNBs and a separate
+production network for the EPC.
+
+In this configuration, OsmoS1GW is deployed at the boundary between the
+two networks. Each eNB connects to the gateway's access-facing SCTP
+listener, and the gateway in turn connects outward to the MME. The eNBs
+never need a route to the core, and the EPC never needs a route to the
+radio access domain.
+
+----
+ +-----------+ +----------+ +-----+
+ | eNB |--S1AP/-->| OsmoS1GW |--S1AP/-->| MME |
+ | (RAN net) | SCTP | (border) | SCTP +-----+
+ +-----------+ +----------+
+ | | PFCP
+ | GTP-U +----+
+ +-------------->| UPF |-----> S-GW (EPC net)
+ +-----+
+----
+
+The gateway acts as the sole point of contact between the two networks,
+providing a natural place to apply access control, logging, and
+monitoring.
+
+[[use_case_mme_pooling]]
+==== MME Pooling
+
+OsmoS1GW supports connecting multiple MMEs in a pool. When an eNB
+connects and performs the S1 Setup procedure, the gateway selects an MME
+from the pool, establishes an SCTP connection to it, and forwards the S1
+Setup Request. If the selected MME rejects the setup or is unreachable,
+the gateway automatically retries with the next candidate in the pool
+before returning a failure to the eNB.
+
+Pool members can be filtered by Tracking Area Code (TAC): each MME entry
+in the pool can carry an optional list of TACs it is willing to serve.
+The gateway uses the TAC list advertised by the eNB in the S1 Setup
+Request to restrict selection to compatible MMEs.
+
+MMEs can be configured statically in the configuration file or managed
+dynamically at run time via the REST API (see <<rest_mme>>).
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/chapters/running.adoc b/doc/manuals/chapters/running.adoc
new file mode 100644
index 0000000..743456f
--- /dev/null
+++ b/doc/manuals/chapters/running.adoc
@@ -0,0 +1,204 @@
+[[running]]
+== Running OsmoS1GW
+
+[[running_requirements]]
+=== Requirements
+
+OsmoS1GW requires:
+
+* Erlang/OTP 25 or later.
+* A Linux kernel with SCTP support (`sctp` kernel module).
+* A reachable UPF that speaks PFCP (e.g. https://osmocom.org/projects/osmo-upf[OsmoUPF]).
+* One or more reachable MMEs (e.g. https://github.com/open5gs/open5gs[Open5GS]).
+
+[[running_installation_options]]
+=== Installation Options
+
+[[running_binary_packages]]
+==== Official Osmocom Binary Packages
+
+Osmocom provides binary packages of OsmoS1GW for a variety of GNU/Linux
+distributions, primarily Debian based ones. This is the recommended
+installation method for production deployments.
+
+Two package feeds are available:
+
+`latest`::
+ Contains the most recent tagged release of each program.
+ Suitable for production use.
+
+`nightly`::
+ Contains automatic nightly builds from the current master branch.
+ Useful for testing new features or bug fixes before they are formally released.
+
+For up-to-date instructions on how to add the Osmocom package repository
+for your distribution, see:
+https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_Packages
+
+[[running_building]]
+==== Building from Source
+
+OsmoS1GW uses https://rebar3.org[rebar3] as its build tool, wrapped by a
+convenience `Makefile` in the project root. To fetch dependencies and
+compile:
+
+----
+git clone https://gitea.osmocom.org/osmocom/osmo-s1gw.git
+cd osmo-s1gw
+make
+----
+
+[[running_building_make_targets]]
+===== Available Make Targets
+
+The following targets are available:
+
+`make` / `make build`::
+ Compile the application and all dependencies (default target).
+
+`make shell` / `make run`::
+ Compile and start OsmoS1GW in an interactive Erlang shell. Intended
+ for development and local testing. The config file used is controlled
+ by the `CONFIG` variable (default: `config/sys.config`).
+
+`make check`::
+ Run the EUnit test suite. Additional arguments can be passed to the
+ test runner via the `EUNIT_ARGS` variable.
+
+`make analyze`::
+ Run Dialyzer static type analysis.
+
+`make release`::
+ Build a self-contained Erlang/OTP release package (includes the ERTS
+ runtime) under `_build/default/rel/osmo-s1gw/`.
+
+`make run-release`::
+ Build the release and immediately start it using the `osmo-s1gw.sh`
+ bootstrap script (see <<running_bootstrap_script>>). The `CONFIG`
+ variable selects the config file.
+
+`make install`::
+ Build the release and install OsmoS1GW system-wide. See
+ <<running_building_installation>> for details.
+
+`make clean`::
+ Remove all build artefacts.
+
+[[running_building_make_variables]]
+===== Make Variables
+
+The following variables customise the build and installation:
+
+[options="header",cols="25,50,25"]
+|===
+| Variable | Description | Default
+| `CONFIG` | Config file used by `make shell` and `make run-release` | `config/sys.config`
+| `EUNIT_ARGS` | Extra arguments forwarded to `rebar3 eunit` | (none)
+| `BINDIR` | Installation directory for executables | `/usr/bin`
+| `LIBDIR` | Installation directory for the release package | `/usr/lib`
+| `CONFDIR` | Installation directory for the config file | `/etc/osmocom`
+| `SYSTEMDUNITDIR` | Installation directory for the systemd unit | `/lib/systemd/system`
+| `DESTDIR` | Staging root prefix (for package builds) | (empty)
+|===
+
+[[running_building_installation]]
+===== Installation
+
+Running `make install` (typically as root, or with `DESTDIR` set for
+packaging) performs the following steps:
+
+* Copies the self-contained Erlang/OTP release to `$(LIBDIR)/osmo-s1gw`
+ (default: `/usr/lib/osmo-s1gw`). This directory bundles the ERTS
+ runtime and all application code, so no separate Erlang installation is
+ required on the target system.
+* Installs the `osmo-s1gw.sh` bootstrap script (see
+ <<running_bootstrap_script>>) as `$(BINDIR)/osmo-s1gw`
+ (default: `/usr/bin/osmo-s1gw`).
+* Installs the `osmo-s1gw-cli.py` management CLI as
+ `$(BINDIR)/osmo-s1gw-cli` (default: `/usr/bin/osmo-s1gw-cli`).
+* Installs the example `config/sys.config` as
+ `$(CONFDIR)/osmo-s1gw.config` (default: `/etc/osmocom/osmo-s1gw.config`).
+* Installs the systemd unit file to `$(SYSTEMDUNITDIR)/osmo-s1gw.service`
+ (default: `/lib/systemd/system/osmo-s1gw.service`).
+
+[[running_options]]
+=== Running Options
+
+[[running_bootstrap_script]]
+==== The `osmo-s1gw` Bootstrap Script
+
+The installed `osmo-s1gw` executable is a POSIX shell script
+(`contrib/osmo-s1gw.sh`) that locates the bundled ERTS runtime inside
+the release package and launches `erlexec` with the correct boot, config,
+and node parameters. It is the standard entry point both for systemd and
+for manual invocation.
+
+Usage:
+
+----
+osmo-s1gw [-s] [-r ROOTDIR] [-c CONFIG] [-C COOKIE] [-n NAME@HOST]
+----
+
+Options:
+
+`-r ROOTDIR`::
+ Path to the Erlang/OTP release root directory.
+ Default: `/usr/lib/osmo-s1gw`.
+
+`-c CONFIG`::
+ Path to the configuration file.
+ Default: `/etc/osmocom/osmo-s1gw.config`.
+
+`-C COOKIE`::
+ Erlang distribution cookie used for inter-node communication.
+ Default: `osmo-s1gw`.
+
+`-n NAME@HOST`::
+ Erlang node name. Default: `osmo-s1gw@<hostname>`.
+
+`-s`::
+ Start with an interactive Erlang shell instead of running headless.
+ Useful for debugging on a deployed system.
+
+[[running_systemd]]
+==== Running Under systemd
+
+After installation, enable and start OsmoS1GW as a systemd service:
+
+----
+systemctl enable osmo-s1gw
+systemctl start osmo-s1gw
+----
+
+The unit file runs OsmoS1GW as the `osmocom` user and group and requests
+the `CAP_NET_ADMIN` capability (required for GTP-U KPI monitoring).
+The service is restarted automatically on failure with a 2-second delay.
+OsmoS1GW reads its configuration from `/etc/osmocom/osmo-s1gw.config`.
+
+To inspect the log output:
+
+----
+journalctl -u osmo-s1gw -f
+----
+
+[[running_logging]]
+=== Logging
+
+OsmoS1GW uses the standard Erlang/OTP `logger` framework. Two log
+handlers are configured by default in `config/sys.config`:
+
+`default`::
+ Writes formatted log lines to standard output. When running under
+ systemd this output is captured by the journal. The log level is set
+ to `info` by default.
+
+`gsmtap`::
+ Sends log messages as GSMTAP frames over UDP to a configurable
+ destination (default: `127.0.0.1`). These frames can be captured with
+ Wireshark and are tagged with the application name `OsmoS1GW`.
+
+The global minimum log level is controlled by the `logger_level` kernel
+parameter; individual handler levels can be overridden independently.
+See <<config_kernel>> for the relevant configuration section.
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/osmo-s1gw-usermanual-docinfo.xml b/doc/manuals/osmo-s1gw-usermanual-docinfo.xml
new file mode 100644
index 0000000..27fd2f3
--- /dev/null
+++ b/doc/manuals/osmo-s1gw-usermanual-docinfo.xml
@@ -0,0 +1,38 @@
+<revhistory>
+ <revision>
+ <revnumber>1</revnumber>
+ <date>March 2026</date>
+ <authorinitials>s</authorinitials>
+ <revremark>Initial version</revremark>
+ </revision>
+</revhistory>
+
+<authorgroup>
+ <author>
+ <firstname>sysmocom</firstname>
+ <surname>- s.f.m.c. GmbH</surname>
+ <email>info@sysmocom.de</email>
+ </author>
+</authorgroup>
+
+<copyright>
+ <year>2025-2026</year>
+ <holder>sysmocom - s.f.m.c. GmbH</holder>
+</copyright>
+
+<legalnotice>
+ <para>
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3 or
+ any later version published by the Free Software Foundation; with no
+ Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
+ copy of the license is included in the section entitled "GNU Free
+ Documentation License".
+ </para>
+ <para>
+ The Asciidoc source code of this manual can be found at
+ <ulink url="https://gitea.osmocom.org/osmocom/osmo-s1gw">
+ https://gitea.osmocom.org/osmocom/osmo-s1gw
+ </ulink>
+ </para>
+</legalnotice>
diff --git a/doc/manuals/osmo-s1gw-usermanual.adoc b/doc/manuals/osmo-s1gw-usermanual.adoc
new file mode 100644
index 0000000..13dcd4b
--- /dev/null
+++ b/doc/manuals/osmo-s1gw-usermanual.adoc
@@ -0,0 +1,22 @@
+OsmoS1GW User Manual
+====================
+:author: sysmocom - s.f.m.c. GmbH
+:toc:
+:numbered:
+:toclevels: 5
+:sectnumlevels: 5
+
+
+include::{commondir}/chapters/preface.adoc[]
+
+include::{srcdir}/chapters/overview.adoc[]
+
+include::{srcdir}/chapters/running.adoc[]
+
+include::{srcdir}/chapters/configuration.adoc[]
+
+include::{commondir}/chapters/glossary.adoc[]
+
+include::{commondir}/chapters/bibliography.adoc[]
+
+include::{commondir}/chapters/gfdl.adoc[]

To view, visit change 42364. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I4ceca069866d7191ef2b153af95a20cb522bffeb
Gerrit-Change-Number: 42364
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>