This guide shows you how to set up PTP on a Linux machine. It is written for someone doing this for the first time. Every command is explained, including the Linux basics around them.
By the end you will have a machine that provides time to other devices on your network, that starts again by itself after a reboot, and that you know how to start, stop, check and remove.
Everything here was run on Ubuntu 24.04, which ships linuxptp 4.0. Where an older release behaves differently the guide says so — there is one such difference, and it stops the configuration file working at all.
Before you start
You need:
- A Linux machine with Ubuntu or Debian. The commands are the same on most distributions; where they differ, the guide says so.
- An account that can use
sudo. Test it withsudo true— if it asks for your password and then says nothing, you are fine. - A network card that supports hardware timestamping. This is where the accuracy comes from, and
Part 1 shows you how to check it with
ethtool. Without it PTP still runs, but no more accurately than NTP. - About 30 minutes.
You do not need to know PTP, systemd or networking. Those are explained as they come up.
What PTP does
PTP keeps clocks on a network in step with each other. One machine acts as the reference. The other devices follow it.
NTP does the same job. So why use PTP? Because PTP is far more accurate. NTP gives you milliseconds. PTP gives you microseconds, and nanoseconds when the network card helps. The card can stamp the exact moment a packet leaves the wire, which removes most of the guesswork.
First tip: do you actually need PTP? If milliseconds are good enough, use chrony or NTP. They are much simpler to run. Choose PTP when you need microseconds, and when your hardware supports it. Setting up PTP on a card with no hardware support gives you NTP-level accuracy for far more effort.
Words you will see
| Word | What it means |
|---|---|
| Grandmaster | The machine that provides the time. Everyone else follows it. Also called the master. |
| Client | A machine or device that follows the grandmaster. Older documents call it a slave. |
| PHC | PTP Hardware Clock. A small clock built into the network card itself. It appears as a file such as /dev/ptp0. |
| Hardware timestamping | The card records the exact send and receive time. This is where the accuracy comes from. |
| ptp4l | The main program. It speaks PTP on the network. |
| phc2sys | A helper program. It copies time between the card’s clock and the system clock. |
| pmc | A small tool that asks ptp4l questions while it is running. |
| Service | A program that Linux runs in the background for you, and restarts after a reboot. |
The one idea to learn first
Your machine has two clocks in this story.
- The system clock. This is the one
dateshows you. Programs use it. - The PHC, inside the network card. Nothing uses it except PTP.
PTP sends the card’s clock to the network, not the system clock. Almost every beginner mistake comes from forgetting this. We will come back to it in Part 5, where it matters most.
Part 1 — Check your network card
Do this before anything else. Most setup problems turn out to be the wrong network card, not a wrong setting.
1.1 List your network cards
ip -br link
You will see a list like this:
lo UNKNOWN
enp0s31f6 UP
wlp0s20f3 DOWN
docker0 DOWN
Names differ from machine to machine. Names starting en are usually wired cards, wl is wireless.
Ignore lo, and ignore anything created by Docker or a virtual machine.
You want a card that says UP and is connected to the network your devices are on.
1.2 Confirm the card is real hardware
ls -l /sys/class/net/ | grep pci
Only physical cards appear in this list. If your card is missing from it, it is virtual — a bridge, a veth, a macvlan or a Docker interface. Virtual cards have no clock inside them and cannot run PTP.
1.3 Check the card supports hardware timestamping
This is the check that decides how accurate your setup can be. Replace eth0 with your card’s name
in every command from here on.
ethtool -T eth0
Look for three things in the output:
hardware-transmitandhardware-receivein the capability list- a line reading
PTP Hardware Clock: 0— the number is what matters, and it tells you the device is/dev/ptp0. If it says 1, your device is/dev/ptp1, and so on. - if it says
PTP Hardware Clock: none, this card cannot do hardware timestamping
Do not trust
ethtool -Ton its own. It answers for virtual cards too, and can report a hardware clock that does not exist. Always do step 1.2 first.
Checkpoint: before continuing, write down two things — your card’s name, and its PHC number.
If your card has no hardware clock, you can still continue. PTP will work in software mode, but the accuracy will be much closer to NTP. It is better to know this now than to wonder later.
Part 2 — Install the software
sudo apt install linuxptp
On RHEL, CentOS or Fedora use sudo dnf install linuxptp.
This gives you three programs: ptp4l, phc2sys and pmc. Nothing needs to be built from source.
Check it worked, and note the version:
ptp4l -v
Checkpoint: you should see a version number. On Ubuntu 24.04 it is 4.0. Write it down — if it
starts with 3 or lower, one line in Part 3 has to change. If you get “command not found”, the install
failed — read the output of the install command again.
| Release | linuxptp version |
|---|---|
| Ubuntu 24.04 (noble) | 4.0 |
| Ubuntu 22.04 (jammy) | 3.1.1 |
| Ubuntu 20.04 (focal) | 1.9.2 |
| Debian 12 (bookworm) | 3.1.1 |
Part 3 — Write the configuration file
PTP reads its settings from a text file. We will create one at
/etc/linuxptp/ptp4l-master.conf.
If you are comfortable with a text editor
sudo nano /etc/linuxptp/ptp4l-master.conf
Type the contents shown below, then press Ctrl+O, Enter to save and Ctrl+X to quit.
Or paste this command, which writes the whole file for you
sudo tee /etc/linuxptp/ptp4l-master.conf > /dev/null <<'CONF'
[global]
network_transport L2
clientOnly 0
tx_timestamp_timeout 100
step_threshold 0.001
logging_level 4
CONF
That command looks strange, so here is what it does. tee writes text into a file. sudo lets it
write into /etc, which normally needs administrator rights. The <<'CONF' … CONF part means
“everything between these two markers is the text to write”. > /dev/null just stops it printing the
text back at you.
What each setting means
| Setting | Meaning |
|---|---|
network_transport L2 |
Send PTP directly over Ethernet. The other choice is UDP over IP. Both work — use the one your devices expect. If you do not know, start with L2. |
clientOnly 0 |
Allow this machine to become the grandmaster. Set it to 1 and the machine will only follow, never lead. |
tx_timestamp_timeout 100 |
How long to wait for the card to report a send timestamp, in milliseconds. |
step_threshold 0.001 |
If the clock is more than 1 ms out, jump it. Below that, adjust it smoothly. |
logging_level 4 |
How much to log. This one surprises people — see Part 4. |
On linuxptp older than 4.0, write
slaveOnly 0instead ofclientOnly 0. TheclientOnlyoption arrived in version 4.0. Ubuntu 22.04 and Debian 12 both ship 3.1.1, which understands onlyslaveOnlyand refuses to start withunknown option clientOnly. On 4.0 and newer both names work, butslaveOnlyis deprecated.
If your card is a VLAN (a name like
eth0.11orvlan11rather thaneth0), add one more line to the file:phc_index N, where N is the PHC number of the parent card, not the VLAN. A VLAN has no clock of its own, soptp4lcannot find one by itself. Without this line it exits immediately withPTP device not specified.
Checkpoint: read the file back and confirm it looks right.
cat /etc/linuxptp/ptp4l-master.conf
Part 4 — Run it by hand first
Do not skip this. Running the program in your terminal is the fastest way to see whether it works, and you will use this same trick every time you change something later.
sudo ptp4l -f /etc/linuxptp/ptp4l-master.conf -i eth0 -m -l 6
-fsays which configuration file to read-isays which network card to use-mprints messages to your screen-l 6raises the amount of detail
You should see something like this within a few seconds:
ptp4l[123.456]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[124.456]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[124.457]: selected local clock 001b21.fffe.0a1b2c as best master
ptp4l[124.457]: assuming the grand master role
assuming the grand master role is what success looks like. Press Ctrl+C to stop it.
If instead it printed an error and exited, go to the Common errors table near the end of this guide. Fix the problem here, in the terminal, before turning it into a service. Debugging a background service is much harder.
Why did I add
-l 6? Because the configuration file setslogging_level 4, which means warnings only. The lines above are info messages at level 6, so at level 4 you would see nothing at all. The numbers are syslog levels — 4 is warning, 6 is info, 7 is debug — and linuxptp’s own default is 6, so the file above is deliberately quieter than stock. Silence later on is normal, and it means “no warnings” rather than “not working”.
Part 5 — Understand phc2sys before you use it
This is the step most guides skip. It causes the worst kind of failure: everything looks healthy and the time is wrong.
Remember the two clocks. ptp4l sends the card’s clock to the network. Nothing has set that
clock. It starts counting from zero when the machine boots, and it drifts.
So without help, your grandmaster serves a time that nobody ever set. Every device follows it perfectly. They all report themselves as synchronised. They are all wrong.
phc2sys fixes this. It copies the system clock into the card’s clock.
5.1 Make sure the system clock is right first
timedatectl
Look for System clock synchronized: yes. If it says no, fix that first with chrony or NTP. PTP
passes on whatever time you give it, including a wrong one.
5.2 Try phc2sys by hand
sudo phc2sys -s CLOCK_REALTIME -c /dev/ptp0 -O 0 -m
Read the flags as a sentence: take the source -s CLOCK_REALTIME, the system clock, and steer the
target -c /dev/ptp0, the card’s clock. On a machine that follows PTP you would use these the other
way round. Getting the direction wrong is a common mistake.
You should see lines like:
/dev/ptp0 sys offset 26 s2 freq -3914 delay 1848
/dev/ptp0 sys offset -10 s2 freq -3942 delay 1803
s2 means locked. s0 and s1 mean it is still settling — wait a few seconds. The offset is in
nanoseconds, so numbers in the tens are very good. Press Ctrl+C to stop.
Never use
-won a grandmaster. That flag waits for the machine to lock onto another master. A grandmaster does not follow anyone, so it waits for ever and appears to hang.
Part 6 — Make it permanent with systemd
So far, everything stops when you close the terminal. systemd is the part of Linux that runs programs in the background and starts them again after a reboot. A program managed this way is called a service.
6.1 The systemd commands you need
Learn these six. They work for every service on the machine, not just PTP.
| Command | What it does |
|---|---|
sudo systemctl start NAME |
Start it now |
sudo systemctl stop NAME |
Stop it now |
sudo systemctl restart NAME |
Stop then start — use after changing a config file |
systemctl status NAME |
Is it running? Shows the last few log lines |
sudo systemctl enable NAME |
Start it automatically at every boot |
sudo systemctl disable NAME |
Do not start it at boot any more |
Two extras worth knowing:
sudo systemctl enable --now NAMEdoesenableandstartin one go.journalctl -u NAMEshows that service’s full log. Add-fto watch it live, or-n 50 --no-pagerfor the last 50 lines.
6.2 Create the PTP service
sudo tee /etc/systemd/system/ptp4l-master.service > /dev/null <<'UNIT'
[Unit]
Description=PTP Master Clock
After=network.target
[Service]
Type=simple
ExecStart=/usr/sbin/ptp4l -f /etc/linuxptp/ptp4l-master.conf -i eth0
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
UNIT
Change eth0 to your card’s name. What the important lines mean:
ExecStart— the exact command to run. It is the same one you ran by hand, without-m -l 6.Restart=alwaysandRestartSec=5— if it stops, start it again after 5 seconds.After=network.target— wait for networking before starting.WantedBy=multi-user.target— this is what makesenablework.
6.3 Create the phc2sys service
sudo tee /etc/systemd/system/phc2sys-master.service > /dev/null <<'UNIT'
[Unit]
Description=Copy the system clock into the network card clock
After=ptp4l-master.service
Requires=ptp4l-master.service
[Service]
Type=simple
ExecStart=/usr/sbin/phc2sys -s CLOCK_REALTIME -c /dev/ptp0 -O 0 -m -q -u 60
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
UNIT
Requires=ptp4l-master.service means this service needs the other one. If PTP stops, this stops too.
-q -u 60 keep the log small: -q stops a duplicate copy going to the system log, and -u 60
prints a summary every 60 updates instead of one line every second. Check both exist on your version
with phc2sys -h — older versions may not have them, in which case leave them out.
6.4 Start both services
Whenever you add or change a file in /etc/systemd/system/, you must tell systemd to re-read it:
sudo systemctl daemon-reload
sudo systemctl enable --now ptp4l-master phc2sys-master
Checkpoint:
systemctl status ptp4l-master
systemctl status phc2sys-master
Both should say active (running) in green. If one says failed, go to Part 8.
Part 7 — Check that it really works
7.1 Are both programs running?
ps aux | grep -E '[p]tp4l|[p]hc2sys'
You should see two lines, one for each program.
7.2 Is this machine the master?
sudo pmc -u -b 0 'GET PORT_DATA_SET'
Look for portState MASTER in the output. That means your machine is providing the time.
-u tells pmc to talk to the local program through a Unix socket on this machine, so it works no
matter which transport you configured.
7.3 Is the card’s clock being kept correct?
journalctl -u phc2sys-master -n 5 --no-pager
You want s2 and offsets in the tens of nanoseconds, as in Part 5.
7.4 Does it survive a reboot?
This is the test people forget.
sudo reboot
When the machine is back:
systemctl status ptp4l-master phc2sys-master
Both should be running again with no action from you. If not, you probably ran start without
enable.
Note:
ptp4lwill now be quiet in the log, because the config file setslogging_level 4(warnings only). That is expected. To watch it work again, stop the service and run it by hand as in Part 4. Never run the service and a hand-started copy at the same time — two programs on one card will fight each other.
Part 8 — When something goes wrong
Read the log
journalctl -u ptp4l-master -n 50 --no-pager
Read the first error, not the last. With
Restart=always, a broken service fails every five seconds and fills the log with identical copies. Scroll up to the beginning.
Clear a stuck failure count
If a service has been failing repeatedly, reset it so the next attempt reads cleanly:
sudo systemctl reset-failed ptp4l-master phc2sys-master
After changing a configuration file
sudo systemctl restart ptp4l-master
Changing /etc/linuxptp/ptp4l-master.conf has no effect until you restart the service. If you change
a .service file, run sudo systemctl daemon-reload first.
Common errors
| Message | What it means | Fix |
|---|---|---|
failed to generate a clock identity |
The card is virtual. It has no MAC address ptp4l can read. |
Use a physical card — Part 1.2. |
PTP device not specified |
You used a VLAN, which has no clock of its own. | Add phc_index N to the config file. |
ioctl SIOCETHTOOL failed: No such device |
The card name does not exist where the service runs. | Check the spelling in ExecStart. Also check you are not inside a container. |
unknown option clientOnly |
linuxptp older than 4.0 — Ubuntu 22.04 and Debian 12 ship 3.1.1. | Use slaveOnly 0 instead. |
Port stays at LISTENING |
Another PTP program is already using this card, or another master is winning. | ps aux | grep ptp4l and stop the extra copy. |
| Service restarts for ever | A configuration error. | Read the very first failure in the log. |
| No output in the log at all | Normal at logging_level 4. |
Raise it to 6, or run by hand with -m -l 6. |
Part 9 — How to undo everything
Useful if you are experimenting, or handing the machine to someone else.
Stop the services and prevent them starting at boot:
sudo systemctl disable --now ptp4l-master phc2sys-master
sudo systemctl reset-failed ptp4l-master phc2sys-master
Remove the files:
sudo rm /etc/systemd/system/ptp4l-master.service
sudo rm /etc/systemd/system/phc2sys-master.service
sudo rm /etc/linuxptp/ptp4l-master.conf
sudo systemctl daemon-reload
Remove the programs as well, if you want:
sudo apt remove linuxptp
Nothing here changes your system clock, so the machine keeps working normally afterwards.
Setting up a machine that follows the master
A grandmaster on its own proves nothing. You need a second machine to see the time arriving. The setup is almost the same, with two differences.
The configuration file, /etc/linuxptp/ptp4l-client.conf:
sudo tee /etc/linuxptp/ptp4l-client.conf > /dev/null <<'CONF'
[global]
network_transport L2
clientOnly 1
logging_level 6
CONF
clientOnly 1 is the first difference: this machine will only follow, never lead. The version note
from Part 3 applies here too — on linuxptp older than 4.0 the line is slaveOnly 1.
Run it by hand first, exactly as in Part 4:
sudo ptp4l -f /etc/linuxptp/ptp4l-client.conf -i eth0 -m
Success here looks different. Instead of assuming the grand master role, you want to see the port
reach SLAVE (or CLIENT on newer versions), followed by lines showing a shrinking offset.
The second difference is the direction of phc2sys. On a client, the card’s clock is the good one and
the system clock follows it:
sudo phc2sys -s /dev/ptp0 -c CLOCK_REALTIME -w -O 0 -m
Note -s and -c have swapped places compared to the master, and -w is now correct — it waits for
ptp4l to synchronise first, which is exactly what you want on a client.
Once both work by hand, turn them into services using the same pattern as Part 6.
Tips
- Start with the card, not the config. Most failures are a wrong or virtual card, not a wrong setting.
- Run by hand before making a service. You see the errors immediately, and you can fix them in seconds instead of reading logs.
- Fix the system clock first. PTP distributes time. It does not check whether that time is correct.
- Always run phc2sys on a grandmaster. Without it you serve a drifting clock and everyone follows it happily.
- One PTP program per card. Two copies on the same card compete and give confusing results.
- Restart after every config change. Editing the file alone does nothing.
- Test the reboot.
enableis what makes a service permanent, notstart. - Keep an eye on log size.
phc2sys -mwrites a line every second. Over days that adds up. - Check the other end too. A device reporting “synchronised” only proves it found a master.
Compare the actual time as well — a master with no
phc2sysproduces exactly this situation.
References
- The Linux PTP Project — https://linuxptp.sourceforge.net/
ptp4lmanual — https://linuxptp.nwtime.org/documentation/ptp4l/phc2sysmanual — https://linuxptp.nwtime.org/documentation/phc2sys/- linuxptp releases — https://github.com/richardcochran/linuxptp/releases
- linuxptp package versions in Ubuntu — https://launchpad.net/ubuntu/+source/linuxptp
- Linux kernel timestamping — https://www.kernel.org/doc/html/latest/networking/timestamping.html
If you watch a phc2sys run settle for more than a few minutes, it is worth doing it inside tmux —
I wrote up sharing a long-running session over SSH with tmux,
which lets you detach and come back to it later, or let a colleague watch the same output.
Did your card turn out to have a hardware clock, or are you running in software mode? I would like to
know which, and if an error sent you to Part 8, tell me in the comments which one it was. If you have
set this up on a VLAN, or on a release older than 24.04 where the slaveOnly line is needed, I would
be glad to hear what else had to change.
Questions or comments?
Ask a question, share your experience, or add a correction below.