PTP on Linux: A Beginner's Guide to Running a Grandmaster Clock

SarbatDaBhalla  · September 19, 2026

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 with sudo 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.

  1. The system clock. This is the one date shows you. Programs use it.
  2. 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-transmit and hardware-receive in 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 -T on 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 0 instead of clientOnly 0. The clientOnly option arrived in version 4.0. Ubuntu 22.04 and Debian 12 both ship 3.1.1, which understands only slaveOnly and refuses to start with unknown option clientOnly. On 4.0 and newer both names work, but slaveOnly is deprecated.

If your card is a VLAN (a name like eth0.11 or vlan11 rather than eth0), 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, so ptp4l cannot find one by itself. Without this line it exits immediately with PTP 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
  • -f says which configuration file to read
  • -i says which network card to use
  • -m prints messages to your screen
  • -l 6 raises 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 sets logging_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 -w on 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 NAME does enable and start in one go.
  • journalctl -u NAME shows that service’s full log. Add -f to watch it live, or -n 50 --no-pager for 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=always and RestartSec=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 makes enable work.

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: ptp4l will now be quiet in the log, because the config file sets logging_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

  1. Start with the card, not the config. Most failures are a wrong or virtual card, not a wrong setting.
  2. Run by hand before making a service. You see the errors immediately, and you can fix them in seconds instead of reading logs.
  3. Fix the system clock first. PTP distributes time. It does not check whether that time is correct.
  4. Always run phc2sys on a grandmaster. Without it you serve a drifting clock and everyone follows it happily.
  5. One PTP program per card. Two copies on the same card compete and give confusing results.
  6. Restart after every config change. Editing the file alone does nothing.
  7. Test the reboot. enable is what makes a service permanent, not start.
  8. Keep an eye on log size. phc2sys -m writes a line every second. Over days that adds up.
  9. 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 phc2sys produces exactly this situation.

References

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.

Loading comments...