Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .project
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
<filteredResources>
<filter>
<id>1790861360617</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -81,6 +83,8 @@ public class Create extends InstallAbstract {
public static final String BIN_ARTEMIS = "bin/" + ARTEMIS;
public static final String ARTEMIS_SERVICE = "artemis-service";
public static final String BIN_ARTEMIS_SERVICE = "bin/" + ARTEMIS_SERVICE;
public static final String ARTEMIS_SERVICE_SYSTEMD = "artemis.service";
public static final String ETC_ARTEMIS_SERVICE_SYSTEMD = "etc/" + ARTEMIS_SERVICE_SYSTEMD;
public static final String ETC_ARTEMIS_PROFILE = "artemis.profile";
public static final String ETC_ARTEMIS_UTILITY_PROFILE = "artemis-utility.profile";
public static final String ETC_LOG4J2_PROPERTIES = "log4j2.properties";
Expand Down Expand Up @@ -340,6 +344,12 @@ public String[] getStaticNodes() {
@Option(names = "--jdbc-lock-expiration", description = "Lock expiration (in milliseconds).")
long jdbcLockExpiration = ActiveMQDefaultConfiguration.getDefaultJdbcLockExpirationMillis();

@Option(names = "--enable-systemd-service", description = "Enable systemd service. Default is false.")
boolean enableSystemdService = false;

@Option(names = "--systemd-service-name", description = "Name of the artemis systemd service. Default is 'artemis'.")
String systemdServiceName = "artemis";

private boolean isAutoCreate() {
if (autoCreate == null) {
if (noAutoCreate != null) {
Expand Down Expand Up @@ -573,6 +583,68 @@ private boolean isDisablePersistence() {
return disablePersistence;
}

public void setSystemdServiceInstall(boolean enableSystemdService) {
this.enableSystemdService = enableSystemdService;
}

public void generateSystemdService(File etcFolder) throws Exception {
Map<String, String> serviceFilters = new LinkedHashMap<>();

// set JAVA_ARGS_APPEND: Set console output level to OFF when runing as a service. Output to logs only.
serviceFilters.put("${java-args-append}", "JAVA_ARGS_APPEND=-Dartemis.console.level=OFF");

@jbertram jbertram Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this preclude using journalctl which is standard practice for services managed by systemd? It seems like if folks want to manage the broker via systemd then the file log should be disabled instead of the console log so they can use journalctl and all the features it provides without duplicate logging.

// set the ARTEMIS_INSTANCE environment variable and the exec-start command to run the broker
serviceFilters.put("${environment}", "ARTEMIS_INSTANCE=" + path(directory));
serviceFilters.put("${exec-start}", path(directory) + "/bin/artemis run");

write(ETC_ARTEMIS_SERVICE_SYSTEMD, new File(etcFolder, systemdServiceName + ".service"), serviceFilters, true, false);
}

public void enableSystemdService() throws Exception {

if (enableSystemdService) {
File systemdServiceFile = new File(directory, "etc/" + systemdServiceName + ".service");
File targetServiceFile = new File("/etc/systemd/system/" + systemdServiceName + ".service");

try { // try enabling the service automatically
Files.copy(systemdServiceFile.toPath(), targetServiceFile.toPath());
getActionContext().out.println("Executing systemctl daemon-reload && systemctl enable " + systemdServiceName + ".service ...");
executeCommand("systemctl", "daemon-reload");
executeCommand("systemctl", "enable", systemdServiceName + ".service");
Comment on lines +611 to +612

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in favor of having the Artemis CLI execute commands like this. Folks familiar with systemd will know how this works and will either do it manually or via a script. We can just document it for folks who are not familiar.


getActionContext().out.println("Systemd unit file was generated and enabled at:");
getActionContext().out.println(String.format(" /etc/systemd/system/%s.service", systemdServiceName));
getActionContext().out.println();
getActionContext().out.println("To start it, execute:");
getActionContext().out.println(String.format(" systemctl start %s.service", systemdServiceName));
} catch (FileAlreadyExistsException e) {
getActionContext().out.println("Service file already exists at " + targetServiceFile.getAbsolutePath() + ".");
} catch (Exception e) {
getActionContext().out.println("Unable to install service: " + e.getMessage());
}
} else { // print out instructions to enable the service
getActionContext().out.println("Systemd unit file was generated at:");
getActionContext().out.println(String.format(" \"%s\"", path(new File(directory, "etc/" + systemdServiceName + ".service"))));
getActionContext().out.println();
getActionContext().out.println("To enable it, run this as root or with sudo privileges:");
getActionContext().out.println(String.format(" cp \"%s\" /etc/systemd/system/%s.service", path(new File(directory, "etc/" + systemdServiceName + ".service")), systemdServiceName));
getActionContext().out.println(String.format(" systemctl daemon-reload && systemctl enable %s.service", systemdServiceName));
}
}

private void executeCommand(String... command) throws Exception {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process process = pb.start();

String output = new String(process.getInputStream().readAllBytes()).trim();
int exitCode = process.waitFor();

if (exitCode != 0) {
throw new RuntimeException(String.format("Command '%s' failed with exit code %d: %s",
String.join(" ", command), exitCode, output));
}
}

@Override
public Object execute(ActionContext context) throws Exception {
this.checkDirectory();
Expand Down Expand Up @@ -796,7 +868,6 @@ public Object run(ActionContext context) throws Exception {

boolean allowAnonymous = isAllowAnonymous();


String retentionTag;
if (retentionDays > 0) {
if (retentionMaxBytes != null) {
Expand Down Expand Up @@ -927,6 +998,11 @@ public Object run(ActionContext context) throws Exception {
}
writeEtc(ETC_JOLOKIA_ACCESS_XML, etcFolder, filters, false);

generateSystemdService(etcFolder);
if (IS_NIX) {
enableSystemdService();
}

context.out.println("");
context.out.println("You can now start the broker by executing: ");
context.out.println("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
Expand Down Expand Up @@ -246,6 +247,19 @@ public Object run(ActionContext context) throws Exception {
//we remove the unwanted wars after updating them above just in case we are upgrading from an older version where the format was different
removeWars(context, bootstrapXml);

// copy the systemd service file if it doesn't exist yet
final File systemdService = new File(etcFolder, Create.ARTEMIS_SERVICE_SYSTEMD);
if (!systemdService.exists()) {
final String instancePath = directory.getCanonicalPath();
final Map<String, String> serviceFilters = new LinkedHashMap<>();
serviceFilters.put("${java-args-append}", "JAVA_ARGS_APPEND=-Dartemis.console.level=OFF");
serviceFilters.put("${environment}", "ARTEMIS_INSTANCE=" + instancePath);
serviceFilters.put("${exec-start}", instancePath + "/bin/artemis run");

context.out.println("Creating " + systemdService);
write(Create.ETC_ARTEMIS_SERVICE_SYSTEMD, systemdService, serviceFilters, true, false);
}

upgradeLogging(context, etcFolder, etcBkp);

context.out.println();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

[Unit]
Description=Apache Artemis Service
After=network-online.target
Wants=network-online.target

[Service]
Type=exec
Environment=${environment}
Environment=${java-args-append}
ExecStart=${exec-start}
TimeoutStopSec=60s
SuccessExitStatus=143
KillMode=mixed
LimitMEMLOCK=infinity
LimitNOFILE=524288
LimitNPROC=31438
LimitAS=infinity
LimitFSIZE=infinity
SendSIGKILL=no
NotifyAccess=all
Restart=always
RestartSec=10
#User=artemis
#Group=artemis

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ appender.console.type=Console
appender.console.name=console
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=%d %-5level [%logger] %msg%n
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = ${sys:artemis.console.level:-INFO}

# Log file appender
appender.log_file.type = RollingFile
Expand Down
1 change: 1 addition & 0 deletions docs/user-manual/_book.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ include::proxy-protocol.adoc[leveloffset=1]

//== Getting Started
include::docker.adoc[leveloffset=1]
include::systemd.adoc[leveloffset=1]
include::using-server.adoc[leveloffset=1]
include::using-cli.adoc[leveloffset=1]
include::client-classpath.adoc[leveloffset=1]
Expand Down
4 changes: 4 additions & 0 deletions docs/user-manual/logging.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ appender.log_file.policies.cron.schedule = 0 0 0 * * ?
appender.log_file.policies.cron.evaluateOnStartup = true
----

While the default console log level is set to `INFO`, the console log level is set to `OFF` via additional java flags in the case of running Apache Artemis as a systemd service.
This is configured in the artemis.service systemd file: `JAVA_ARGS_APPEND=-Dartemis.console.level=OFF`.
This is to avoid the overhead of logging to both the console and the file. Any potential errors at startup will still be visible when checking the systemd service logs, by running `journalctl -u artemis` or similar commands.

== Configuring Broker Audit Logging

There are 3 audit loggers that can be enabled separately and audit different types of broker events, these are:
Expand Down
72 changes: 72 additions & 0 deletions docs/user-manual/systemd.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
= Systemd
:idprefix:
:idseparator: -
:docinfo: shared

== Automatic systemd service generation

A systemd service file is generated automatically when you create the broker via cli. The file is available at `pathToBrokerInstance/etc/artemis.service`.

The contents of the automatically generated file look like this:

[,console]

----
[Unit]
Description=Apache Artemis Service
After=network.target network-online.target
Wants=network-online.target

[Service]
Type=exec
Environment=ARTEMIS_INSTANCE=/pathToBrokerInstance
Environment=JAVA_ARGS_APPEND=-Dartemis.console.level=OFF
ExecStart=/pathToBrokerInstance/bin/artemis run
TimeoutStopSec=60s
SuccessExitStatus=143
KillMode=mixed
LimitMEMLOCK=infinity
LimitNOFILE=524288
LimitNPROC=31438
LimitAS=infinity
LimitFSIZE=infinity
SendSIGKILL=no
NotifyAccess=all
Restart=always
RestartSec=10
#User=artemis
#Group=artemis

[Install]
WantedBy=multi-user.target
----
Comment on lines +10 to +33

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating the contents of the file here is going to create a maintenance burden. I recommend simply referencing the file so users can find the content of the file directly themselves.


You might want to tweak or add additional configuration inside the service file, for example:

* uncomment and/or change `User` with which to run the service, to avoid running as root
* add `Nice` to tweak niceness of the java process
* add `Alias`
* increase or decrease `TimeoutStopSec` and `RestartSec`
* tweak the console log level, which is set to `OFF` to avoid the overhead of logging to both file and console
Comment on lines +35 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These might be better as comments in the service file itself.


You can read more about systemd https://systemd.io/[here].

== Enable systemd service via flags

It is also possible to automate the service installation via `--enable-systemd-service` and `--systemd-service-name` flags.
In order to do this, the broker creation script usually needs to be run with `sudo` or `root` privileges.

To enable the service automatically, and to change its name (from the default `artemis`), run:

`./artemis create brokername --enable-systemd-service --systemd-service-name=artemisTest`

You can now use `systemctl` commands to start/stop/restart the service, named `artemisTest`:

[,console]
----
systemctl start artemisTest
systemctl stop artemisTest
systemctl restart artemisTest
----

You can read the systemctl man page https://man7.org/linux/man-pages/man1/systemctl.1.html[here].
8 changes: 8 additions & 0 deletions docs/user-manual/versions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ NOTE: Follow the general upgrade procedure outlined in the xref:upgrading.adoc#u
* AMQP message size estimation has been improved to account for the full message metadata, fixing underestimates that occurred when messages carried large application properties.
* AMQP broker connection Senders, Receivers and Peer configurations have been deprecated and will be removed in a future release.
Users of the AMQP broker connection Senders and Receivers are encouraged to migrate to the newer AMQP Bridge configurations that provide more robust and configurable send to and receive from topologies.
* https://issues.apache.org/jira/browse/ARTEMIS-6261[ARTEMIS-6261] - Run artemis as a systemd service
Automated systemd unit file generation has been added to the broker instance creation tool.
The service is not enabled by default.
If running the creation script with `sudo` or `root` privileges, you can pass `--enable-systemd-service` to automatically enable the service at system startup.
The service file will then be placed in `/etc/systemd/system` and the commands `systemctl daemon-reload` and `systemctl enable artemis.service` will be executed automatically.
To customize the unit name use the `--systemd-service-name` flag (e.g., `--systemd-service-name=artemis-broker`).
The service can then be started/stopped by using commands like `systemctl start/stop artemis`.
This native systemd integration is preferred over the legacy `artemis-service` script.
Comment on lines +27 to +34

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Highlights here should be short and sweet. Details should be available via hyperlinks for users who want more info.


=== Upgrading from 2.57.0

Expand Down