Apache NiFi is an open-source platform for moving and transforming data between systems. You design flows in a web UI by connecting processors, and NiFi handles queuing, back pressure, retries and data provenance for every piece of data it touches. In this tutorial you will install Apache NiFi 2 on Ubuntu 24.04, run it as a systemd service under its own user, reach the UI securely through an SSH tunnel and build a first flow that picks up CSV files, converts them to JSON and writes them to another directory.
Prerequisites
- A server running Ubuntu 24.04 LTS with at least 2 vCPUs, 4 GB of RAM and 20 GB of free disk, for example a CubePath VPS. Production flows usually need 8 GB of RAM or more.
- A non-root user with
sudoprivileges. - An SSH client on your local machine, used to open a tunnel to the NiFi UI.
Step 1 - Installing Java 21
NiFi 2.x requires Java 21. Ubuntu 24.04 packages it, along with unzip, which you need to extract the release:
sudo apt update
sudo apt install -y openjdk-21-jre-headless unzip
Verify the Java version:
java -version
openjdk version "21.0.8" 2025-07-15
OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1)
OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing)
The exact build number will differ; what matters is that the major version is 21.
Step 2 - Downloading and verifying NiFi
Check the latest 2.x release on the NiFi download page and set it in a variable. This tutorial uses 2.4.0 as the example; the Apache archive keeps every release, so the URL keeps working after newer versions come out:
NIFI_VERSION=2.4.0
cd /tmp
curl -fLO https://archive.apache.org/dist/nifi/${NIFI_VERSION}/nifi-${NIFI_VERSION}-bin.zip
curl -fLO https://archive.apache.org/dist/nifi/${NIFI_VERSION}/nifi-${NIFI_VERSION}-bin.zip.sha512
Compare the checksum of the download with the published one:
sha512sum nifi-${NIFI_VERSION}-bin.zip
cat nifi-${NIFI_VERSION}-bin.zip.sha512
Both commands must print the same 128-character hash. If they differ, delete the file and download it again.
Step 3 - Installing NiFi under a dedicated user
Create a system user without a login shell to run NiFi:
sudo useradd --system --home-dir /opt/nifi --shell /usr/sbin/nologin nifi
Extract the release into /opt/nifi and create a current symlink, so upgrades only need the link changed:
sudo mkdir -p /opt/nifi
sudo unzip -q /tmp/nifi-${NIFI_VERSION}-bin.zip -d /opt/nifi
sudo ln -sfn /opt/nifi/nifi-${NIFI_VERSION} /opt/nifi/current
sudo chown -R nifi:nifi /opt/nifi
By default NiFi stores its repositories (FlowFile, content, provenance and state) inside the installation directory, next to conf/ and logs/. That is fine for a single server; on larger deployments you can point them to separate disks in conf/nifi.properties.
Step 4 - Setting the login credentials
A fresh NiFi 2 install uses single-user authentication over HTTPS with a self-signed certificate. If you do nothing, NiFi generates a random username and password on first start and prints them in the log. Setting your own before the first start is cleaner. The password must be at least 12 characters:
sudo -u nifi /opt/nifi/current/bin/nifi.sh set-single-user-credentials admin 'your_strong_password'
Replace your_strong_password with a password of your own. The command stores a bcrypt hash of it in conf/login-identity-providers.xml.
Step 5 - Running NiFi as a systemd service
Create a unit file:
sudo nano /etc/systemd/system/nifi.service
[Unit]
Description=Apache NiFi
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
User=nifi
Group=nifi
ExecStart=/opt/nifi/current/bin/nifi.sh start
ExecStop=/opt/nifi/current/bin/nifi.sh stop
LimitNOFILE=50000
LimitNPROC=10000
TimeoutStartSec=180
Restart=on-failure
[Install]
WantedBy=multi-user.target
nifi.sh start launches a bootstrap process that starts and supervises the NiFi JVM, which is why the unit uses Type=forking. NiFi opens many files at once, so the unit raises the open file limit well above the default.
Load the unit and start NiFi:
sudo systemctl daemon-reload
sudo systemctl enable --now nifi
The first start takes one to two minutes. Wait until the log reports that the UI is available:
sudo tail -f /opt/nifi/current/logs/nifi-app.log | grep --line-buffered "UI is available"
2026-03-10 14:02:11,512 INFO [main] org.apache.nifi.web.server.JettyServer NiFi has started. The UI is available at the following URLs:
Press Ctrl+C, then confirm NiFi answers locally:
curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1:8443/nifi/
200
Step 6 - Accessing the UI through an SSH tunnel
NiFi 2 listens on 127.0.0.1:8443 by default (nifi.web.https.host in conf/nifi.properties), so it is not reachable from the Internet, and you do not need to open any port in UFW. The simplest secure way to reach it is an SSH tunnel. Run this on your local machine:
ssh -L 8443:127.0.0.1:8443 your_user@your_server_ip
Keep the session open and browse to https://localhost:8443/nifi. Your browser warns about the self-signed certificate; accept it for this host. Log in with admin and the password from Step 4. You see an empty canvas: the root process group.
TipIf several people need access, put NiFi behind a reverse proxy with a trusted certificate and configure an identity provider such as OIDC or LDAP, instead of sharing the single-user credentials.
Step 7 - Building a CSV to JSON flow
The flow reads CSV files from an input directory, converts each one to a JSON array, renames it and writes it to an output directory. Create the input and output directories on the server:
sudo mkdir -p /opt/nifi/data/in /opt/nifi/data/out
sudo chown -R nifi:nifi /opt/nifi/data
NiFi concepts used in this flow:
- A FlowFile is one unit of data: its content plus attributes such as
filename. - A processor does one job and routes each FlowFile to a named relationship, such as
successorfailure. - A connection is a queue between a relationship and the next processor.
- A controller service is a shared component, such as a record reader, used by several processors.
Adding the processors
Drag the Processor icon from the top toolbar onto the canvas, type the name in the search box and click Add. Add four processors and configure each one by double-clicking it and opening the Properties tab:
- GetFile: set Input Directory to
/opt/nifi/data/in. It picks up files and, by default, deletes them from the directory once they are in NiFi. - ConvertRecord: for Record Reader, open the dropdown and choose Create new service, then select CSVReader. Do the same for Record Writer with JsonRecordSetWriter.
- UpdateAttribute: click + to add a property named
filenamewith the value${filename:substringBeforeLast('.')}.json. This uses the NiFi Expression Language to change the extension. - PutFile: set Directory to
/opt/nifi/data/outand Conflict Resolution Strategy toreplace.
Configuring the controller services
Right-click an empty area of the canvas and choose Controller Services. Open the CSVReader settings and set:
- Schema Access Strategy:
Infer Schema - Treat First Line as Header:
true
Leave JsonRecordSetWriter with its defaults, which write the records using the schema of the reader. Enable both services with the lightning bolt icon (or Enable from each service's menu). A processor that uses a disabled service stays invalid.
Connecting the processors
Hover over a processor, drag the arrow that appears onto the next processor and choose the relationship:
- GetFile to ConvertRecord on
success. - ConvertRecord to UpdateAttribute on
success. - UpdateAttribute to PutFile on
success.
Every relationship must either be connected or auto-terminated, otherwise the processor shows a warning icon. Open ConvertRecord and, in the Relationships tab, tick terminate for failure. In PutFile, terminate both success and failure. In production you would route failures to a separate directory or an alert instead of discarding them.
Starting and testing the flow
Right-click an empty area of the canvas and choose Start. All four processors should show a green play icon. On the server, drop a CSV file into the input directory:
sudo -u nifi tee /opt/nifi/data/in/orders.csv > /dev/null <<'EOF'
id,customer,amount
1,alice,120.50
2,bob,75.00
3,carol,210.99
EOF
After a few seconds the file disappears from in/ and a JSON file appears in out/:
sudo cat /opt/nifi/data/out/orders.json
[{"id":1,"customer":"alice","amount":120.5},{"id":2,"customer":"bob","amount":75.0},{"id":3,"customer":"carol","amount":210.99}]
To see what happened to the file, right-click PutFile and choose View Data Provenance. Each event shows the FlowFile's attributes, its content before and after each step and its full lineage.
Step 8 - Adjusting the Java heap
NiFi starts with a 1 GB heap. On a server with 8 GB of RAM or more, raise it in conf/bootstrap.conf:
sudo -u nifi nano /opt/nifi/current/conf/bootstrap.conf
Change the two memory lines, for example to 4 GB:
java.arg.2=-Xms4g
java.arg.3=-Xmx4g
Leave at least a third of the server's memory free for the operating system's page cache, which NiFi's content repository relies on. Restart the service to apply the change:
sudo systemctl restart nifi
Troubleshooting
NiFi does not start or stops shortly after starting. Read /opt/nifi/current/logs/nifi-app.log and /opt/nifi/current/logs/nifi-bootstrap.log. java.lang.OutOfMemoryError means the heap is too small for the flow; a message about the Java version means Java 21 is not the default (sudo update-alternatives --config java).
Login fails with the credentials you set. Run set-single-user-credentials again as the nifi user with a password of at least 12 characters, then restart the service.
A processor stays invalid. Hover over the warning icon to see the reason. It is usually a required property, an unconnected relationship or a controller service that is not enabled.
Files stay in the input directory. The nifi user must be able to read and delete them. Check ownership with ls -l /opt/nifi/data/in and make sure GetFile is running.
Queues fill up and upstream processors stop. That is back pressure working: a connection reached its object or size threshold (10,000 FlowFiles or 1 GB by default). Find the slow processor downstream, or right-click the connection and choose List queue to inspect what is waiting.
Conclusion
Apache NiFi 2 now runs as a systemd service on Ubuntu 24.04, reachable only through an SSH tunnel, with a working flow that converts CSV to JSON and full provenance for every file. Next, you can replace GetFile with a source such as QueryDatabaseTableRecord or ConsumeKafka, set up a reverse proxy with an OIDC identity provider for multi-user access, or version your flows in a Git-backed registry client.
