Argent Portage Central Configuration
System Administration
This is the system administration sequence, starting with the heart of every Gentoo based system: /etc/portage.
First, something you have to know: Argent is a complete Gentoo. Same portage, same ebuilds, same profiles, same USE flags, same /etc/portage, with every regular Gentoo feature. What Argent adds on top is a central configuration, a binhost built with that configuration, and tools like epkg and avasile to keep your system in line with them.
So everything the Gentoo documentation says applies to Argent too, and you should read it before you touch /etc/portage:
- Gentoo Handbook: Portage, how portage works, how it syncs, how it installs and updates packages
- Gentoo Handbook: USE flags, what USE flags are, global and per package, how to set them
- Gentoo Handbook: Portage features, the
FEATURESvariable in make.conf, likebuildpkg,parallel-fetchorsplitdebug
This page only explains what is different on Argent.
How /etc/portage works on Argent
On Argent, /etc/portage is a git directory. Actuall a symlink to a git repo:
/etc/portage -> /opt/argentws-build/conf/intel/portage
and /opt/argentws-build is a git clone of our central configuration repository:
https://gitlab.com/argent/argentws-build.git
avasile sets this up for you when you switch modes (--usermode, --devmode, --srcmode). The only thing that changes between modes is which make.conf is active:
/etc/portage/make.conf/00-main.conf -> make.conf.amd64-user (user mode)
/etc/portage/make.conf/00-main.conf -> make.conf.amd64-devel (devmode)
/etc/portage/make.conf/00-main.conf -> make.conf.amd64-srcmode (srcmode)
To see which mode you are on:
readlink -f /etc/portage/make.conf/*
Why is /etc/portage under git
Because the binary packages on our binhost are built with exactly this configuration. The USE flags, keywords, masks and make.conf you have are the same ones our build server used. If your configuration drifts away from it, the binaries stop matching your system, and portage starts compiling things you didn't ask for (or, in user mode, silently ignores what you changed).
So git gives us:
- every Argent machine has the same configuration, the one the binaries were built with
- one
epkg updatebrings you the new configuration together with the new packages - every change we make is public, with history, on gitlab (for now)
- switching modes is just changing one symlink
What epkg update does to /etc/portage
At every epkg update, /opt/argentws-build is reset to exactly what is on our server:
git fetch --depth=1 origin master && git reset --hard origin/master && git clean -fd
This means:
- any change you make to an Argent file is lost at the next update
- any new file of yours that git doesn't ignore is deleted at the next update
- files that git ignores are left alone, and this is where your own configuration goes
epkg devsync does a plain git pull instead. If you changed an Argent file, the pull stops with a conflict, and you have to restore the file (see below) before it can continue.
Argent files and your files
Every directory in /etc/portage has a .gitignore that works as a whitelist: it ignores every file with a dot in its name (*.*), except the Argent files, which are listed one by one.
The Argent files start with 00-, like 00-argent.package.use. Don't edit them.
Your files:
- must have a dot in their name, otherwise git doesn't ignore them and
epkg updatedeletes them - should start with a bigger number than
00-, so they are read after ours and have priority over them
The convention is 100-my.<something>:
/etc/portage/package.use/100-my.package.use
/etc/portage/package.accept_keywords/100-my.package.keywords
/etc/portage/package.mask/100-my.package.mask
/etc/portage/package.unmask/100-my.package.unmask
/etc/portage/package.env/100-my.package.env
/etc/portage/make.conf/01-my.make.conf
Don't name a file 00-my.package.keywords, that name is on the Argent whitelist, so git doesn't protect it.
Keep a copy of your files before you switch modes. avasile --usermode, --devmode, --srcmode and --custom delete the whole /opt/argentws-build and clone it again, and your files go away with it. epkg update doesn't do this, only a mode switch does.
make.conf
make.conf is the main configuration of portage. It's where Gentoo keeps the settings for the whole system:
- how packages are compiled:
COMMON_FLAGS,CFLAGS,CXXFLAGS,MAKEOPTS - the global USE flags:
USE, and the USE flags written as variables, likeVIDEO_CARDS,L10N,PYTHON_TARGETS - how portage behaves:
FEATURES,EMERGE_DEFAULT_OPTS - where things are kept:
PKGDIR(binary packages),DISTDIR(sources),PORTDIR(the portage tree) - which licenses you accept:
ACCEPT_LICENSE, and where sources are downloaded from:GENTOO_MIRRORS
It's written like a shell script, VARIABLE="value", and a variable can use another one, like CFLAGS="${COMMON_FLAGS}". The Gentoo documentation is here, and all the variables are in:
man make.conf
make.conf as a directory
On Gentoo, /etc/portage/make.conf can be a single file or a directory. When it's a directory, portage reads every file in it in alphabetical order, as if they were one big make.conf, and when the same variable is set twice, the last one has priority.
Argent uses it as a directory. The main file is a symlink to our make.conf for the mode you are on:
/etc/portage/make.conf/00-argent.conf -> /opt/argentws-build/conf/intel/portage/make.conf.amd64-devel
(or 00-main.conf, same thing)
The main file must be called 00-argent.conf, 00-main.conf or main.conf. These are the names epkg looks for, if it can't find one of them, epkg fails to run. Don't rename it, and don't replace it with your own.
The three Argent make.conf files are the same, except for how they use the binhost:
make.conf.amd64-user:--getbinpkgonly, only binariesmake.conf.amd64-devel:--getbinpkgandFEATURES=buildpkg, binaries when they match, compile and save the binary when they don'tmake.conf.amd64-srcmode: no binhost, compile everything and save the binaries
Your own make.conf
Next to ours, you can keep your own:
/etc/portage/make.conf/01-my.make.conf
It's read after ours, so whatever you set there has priority over ours. The whole make.conf directory is ignored by git, so epkg update leaves it alone. For example:
MAKEOPTS="-j16"
VIDEO_CARDS="amdgpu radeonsi"
L10N="en en-US ro ro-RO"
USE="${USE} -wayland"
Things to know:
MAKEOPTS,COMMON_FLAGSand the other compiler settings only matter for what you compile yourself. If you use-march=native, what you compile (and what gets saved in/var/cache/binpkgs) runs only on your CPU- everything that changes USE flags (
USE,VIDEO_CARDS,L10N,PYTHON_TARGETS, ...) means compiling in devmode, and has no effect in user mode, see USE flags below - don't change
PORTDIRorGENTOO_DISTRO,epkgdepends on them
The moment you do this, you are deriving away from Argent. Your system is no longer the one our binaries were built for, and we can't help you anymore with the issues specific to your setup. But that's what Gentoo is in the end: your system, your configuration, and back to reading the documentation.
make.conf.local
/etc/portage/make.conf.local is not a portage file, portage never reads it. Only epkg reads it, right after the main make.conf, so whatever you put there overrides the main make.conf, for epkg only. avasile and epkg create it empty.
Today it matters only for the few variables epkg reads directly from make.conf when it starts, like PORTDIR and GENTOO_DISTRO. PKGDIR is not one of them, epkg asks portage for it, so setting it in your 01-my.make.conf is enough. Most users should leave make.conf.local empty.
USE flags
The global USE flags live in the active make.conf (make.conf.amd64-user, make.conf.amd64-devel, ...), grouped by topic: SYSTEM_USE, CODECS_USE, MEDIA_USE, SOUND_USE and so on. The per package USE flags live in /etc/portage/package.use/00-*.package.use.
If USE flags are new to you, read the Gentoo Handbook on USE flags first, the rest of this section assumes you know what they are.
In user mode
Don't change USE flags in user mode. User mode installs only binary packages (--getbinpkgonly), and in this case portage doesn't check if the USE flags of the binary match yours. You get our binaries, built with our USE flags, whatever you set, so your change simply does nothing.
If you need different USE flags, switch to devmode first:
avasile --devmode
In devmode
Here you can change USE flags. When your USE flags are the same as ours, portage installs the binary from our binhost. When they differ, portage compiles that package for you, and saves the result in /var/cache/binpkgs so you don't compile it again.
To see which USE flags a package has, and which ones are active:
equery uses <package>
To change them for one package, add a line to your own file:
echo "media-video/mpv lua -wayland" >> /etc/portage/package.use/100-my.package.use
To change them globally, use your own make.conf file (see make.conf above):
echo 'USE="${USE} -wayland"' >> /etc/portage/make.conf/01-my.make.conf
Keep the ${USE} in there, otherwise you throw away all our USE flags, not only the one you wanted to change.
Then see what would be rebuilt, and do it:
epkg upgrade
epkg upgrade already rebuilds every package whose USE flags changed. For only one package:
epkg src-newuse <package>
Every USE flag you change is one more package you compile yourself, and one more package that no longer follows the binhost. Change only what you really need.
Looking into the git
Since /etc/portage is a git repository, you can use git to see what is going on:
cd /etc/portage
By default you have only the last commit (epkg update fetches with --depth=1). You can see the whole history on gitlab, or bring it locally with:
epkg force-sync
Then, what we changed lately:
git log --oneline
What we changed in one file, and why:
git log -p package.use/00-argent.package.use
The next epkg update makes it shallow again.
If you changed any Argent file by mistake:
git status
git diff
To restore an Argent file you changed:
git checkout -- package.use/00-argent.package.use
To see your own files (the ones git ignores):
git status --ignored
Never commit anything here. At the next epkg update your commit is thrown away by the reset, together with everything in it.
Leaving the central configuration
If you want /etc/portage fully yours, disconnected from Argent, avasile has the --custom and --decentralize-* modes. They are for advanced Gentoo users, read avasile --help carefully before using them. --decentralize-gentoo is a one way ticket.
Portage
Portage on Argent is the regular Gentoo portage. epkg is only a wrapper around it, so you can always use emerge, equery, qlist and the rest of the Gentoo tools directly. The mode you are on still applies: in user mode, emerge installs only binaries too, because --getbinpkgonly is set in the make.conf.
For how portage itself works, the Gentoo Handbook: Portage is the reference. Below is only what Argent does differently.
Repositories
Argent uses two repositories, both defined in /etc/portage/repos.conf/:
argent-ws in /var/db/repos/argent-ws, synced from https://gitlab.com/argent/argent-ws.git
gentoo in /var/db/repos/gentoo, synced from https://gitlab.com/argent/portage.git
argent-ws is the main repository (main-repo = argent-ws), with our own packages, our fixes and our profiles. It has a higher priority (50) than gentoo (1), so when both have the same version of a package, ours has priority.
The gentoo repository is our snapshot of the Gentoo tree, not the live Gentoo one, so the ebuilds you have match the binaries you get. Don't point it to the Gentoo servers, you will get ebuilds that are newer than our binaries and you'll end up compiling half of the system.
To see which one is the main repository on your system:
portageq repositories_configuration / | grep main-repo
In user mode, both repositories are minimal: only profiles, metadata and eclass, no ebuilds. You don't need ebuilds to install binaries. In devmode and srcmode you get the full trees.
Your own overlays
You can add any other overlay the Gentoo way, for example with eselect repository:
eselect repository enable guru
It writes /etc/portage/repos.conf/eselect-repo.conf, which has a dot in its name, so it survives epkg update. If you write the repos.conf file by hand, follow the same rule, like /etc/portage/repos.conf/100-my-overlay.conf.
Keep in mind:
epkg updatesyncs onlygentooandargent-ws, useepkg devsyncoremaint sync -r <overlay>for yours- our binhost has nothing from your overlays, everything from there gets compiled, so overlays make sense only in devmode or srcmode
Example: your own kernel
A good reason for your own overlay is your own kernel: our sources with a different config, or a different patched source (linux-tkg, for example) with your config. You don't edit our ebuilds (epkg update resets them), you make your own kernel package, with your own name.
You need devmode for this, in user mode argent-ws has no ebuilds to fetch our kernel sources with:
avasile --devmode
Pick one name and use it everywhere. Here it is mykernel:
- the packages:
linux-mykernelandmykernel-sources - the kernel:
6.12.110-mykernel, it installs next to6.12.110-argent, not over it - the tarball:
/var/cache/distfiles/linux-6.12.110-mykernel.tar.xz - the directory inside the tarball:
linux-6.12.110-mykernel/ - the config inside that directory:
mykernel/config/mykernel-6.12-amd64.config K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"in both ebuilds
The eclass uses this name for the tarball, the config, the initramfs and the DKMS modules. If one of them still says argent, dracut builds the initramfs for our kernel instead of yours, and removing your kernel deletes ours.
1. Create your overlay
eselect repository create myoverlay
It lives in /var/db/repos/myoverlay. Our kernel ebuilds use the argent-kernel eclass from argent-ws, so your overlay has to see it. Edit /var/db/repos/myoverlay/metadata/layout.conf:
masters = gentoo argent-ws thin-manifests = true
2. Prepare the source tarball
This is the first step, nothing after it works without it. The ebuilds don't download your kernel, they take it from /var/cache/distfiles, so it has to be there, with the right name, before you write them.
Start from our sources. Download our tarball and unpack it under your name:
epkg fetchsourcepkg =sys-kernel/argent-sources-6.12.110
cd /var/cache/distfiles
tar -xJf linux-6.12.110-argent.tar.xz
mv linux-6.12.110-argent linux-6.12.110-mykernel
cd linux-6.12.110-mykernel
Make your config, starting from ours:
cp argent/config/argent-6.12-amd64.config .config
make menuconfig
Put it where the eclass looks for it (<name>-<major.minor>-amd64.config), remove our config, and clean the tree:
mkdir -p mykernel/config
cp .config mykernel/config/mykernel-6.12-amd64.config
rm -r argent
make mrproper
For a different source (linux-tkg, a vanilla kernel with your patches, ...) it's the same: the patched tree goes in linux-6.12.110-mykernel/, your config in mykernel/config/. The version in the directory name has to be the version of the ebuild.
Pack it from /var/cache/distfiles, so the tarball starts with the directory:
cd /var/cache/distfiles
tar -pcJf linux-6.12.110-mykernel.tar.xz linux-6.12.110-mykernel
Check it, the first line must be linux-6.12.110-mykernel/:
tar -tJf linux-6.12.110-mykernel.tar.xz | head -1
3. Write the ebuilds
cd /var/db/repos/myoverlay
mkdir -p sys-kernel/linux-mykernel sys-kernel/mykernel-sources
sys-kernel/linux-mykernel/linux-mykernel-6.12.110.ebuild:
EAPI=8 K_ROGKERNEL_SELF_TARBALL_NAME="mykernel" K_REQUIRED_LINUX_FIRMWARE_VER="20260622" K_ROGKERNEL_FORCE_SUBLEVEL="110" K_ROGKERNEL_FORCE_UPPERLEVEL="6.12" K_ROGKERNEL_PATCH_UPSTREAM_TARBALL="0" K_KERNEL_NEW_VERSIONING="1" inherit argent-kernel KEYWORDS="amd64" DESCRIPTION="My own kernel image" RESTRICT="mirror" IUSE="grub2"
sys-kernel/mykernel-sources/mykernel-sources-6.12.110.ebuild:
EAPI=8
K_ROGKERNEL_FORCE_SUBLEVEL="110"
K_ROGKERNEL_FORCE_UPPERLEVEL="6.12"
K_ROGKERNEL_NAME="mykernel"
K_ROGKERNEL_URI_CONFIG="yes"
K_ROGKERNEL_SELF_TARBALL_NAME="mykernel"
K_ONLY_SOURCES="1"
K_KERNEL_NEW_VERSIONING="1"
inherit argent-kernel
KEYWORDS="amd64"
DESCRIPTION="My own kernel sources"
RESTRICT="mirror"
IUSE="grub2 sources_standalone"
DEPEND="${DEPEND}
sources_standalone? ( !=sys-kernel/linux-mykernel-${PVR} )
!sources_standalone? ( =sys-kernel/linux-mykernel-${PVR} )"
What changed compared to ours:
K_ROGKERNEL_SELF_TARBALL_NAMEismykernelin bothK_ROGKERNEL_NAMEismykernelin the sources ebuild (inlinux-mykernelit comes from the package name by itself)- the sources depend on
linux-mykernel, not onlinux-argent
The download address in the ebuilds points to our server, where your tarball doesn't exist. That's fine, portage finds it in /var/cache/distfiles and doesn't download anything.
Optional: keep your config next to the ebuilds
The config inside the tarball is enough. If you'd rather change the config without packing the tarball again, keep a copy in files/ of both packages, and let src_prepare() copy it over the one from the tarball:
mkdir -p sys-kernel/linux-mykernel/files sys-kernel/mykernel-sources/files
cp /var/cache/distfiles/linux-6.12.110-mykernel/mykernel/config/mykernel-6.12-amd64.config sys-kernel/linux-mykernel/files/
cp /var/cache/distfiles/linux-6.12.110-mykernel/mykernel/config/mykernel-6.12-amd64.config sys-kernel/mykernel-sources/files/
And add this at the end of both ebuilds:
src_prepare() {
argent-kernel_src_prepare
cp "${FILESDIR}/mykernel-6.12-amd64.config" "${S}/mykernel/config/" || die
}
From now on, the file in files/ has priority over the one in the tarball. Change it there, in both packages. Your overlay uses thin manifests, so it needs no new manifest. When the major version changes, the file name in src_prepare() changes too.
After a config change the version stays the same, and in devmode portage would install the binary it saved last time in /var/cache/binpkgs. Rebuild without it:
epkg install --getbinpkg=n --usepkg=n sys-kernel/mykernel-sources sys-kernel/linux-mykernel
4. Manifest and install
The manifest is made from your tarball in /var/cache/distfiles:
ebuild sys-kernel/linux-mykernel/linux-mykernel-6.12.110.ebuild manifest
ebuild sys-kernel/mykernel-sources/mykernel-sources-6.12.110.ebuild manifest
epkg install sys-kernel/mykernel-sources
This pulls in linux-mykernel too, and compiles both, there is no binary for your kernel on our binhost. With USE=grub2, the grub menu is regenerated at the end, otherwise do it yourself:
grub-mkconfig -o /boot/grub/grub.cfg
And rebuild the external modules (nvidia, virtualbox, zfs, ...) for your new kernel:
epkg module-rebuild
5. Keeping it up to date
Your kernel doesn't follow ours anymore. For a new version, you go through step 2 again with the new source (linux-6.12.114-mykernel, for example), copy your ebuilds to the new version, and change K_ROGKERNEL_FORCE_SUBLEVEL. If the major version changes (6.12 to 6.18 for example), K_ROGKERNEL_FORCE_UPPERLEVEL and the config name change too (mykernel-6.18-amd64.config), and the config needs a look with make oldconfig.
Keep your tarball in /var/cache/distfiles, portage needs it every time your kernel gets rebuilt.
If you pack the tarball again for the same version (a new config, a new patch), the checksums in the manifests don't match it anymore. Delete both manifests first, otherwise ebuild ... manifest moves your new tarball aside as a failed download:
rm sys-kernel/linux-mykernel/Manifest sys-kernel/mykernel-sources/Manifest
Make them again as in step 4, and rebuild without the binary portage saved last time:
epkg install --getbinpkg=n --usepkg=n sys-kernel/mykernel-sources sys-kernel/linux-mykernel
Keep a copy of /etc/portage/repos.conf/eselect-repo.conf, a mode switch with avasile removes it (your overlay in /var/db/repos/myoverlay stays).
Binhost
The binary packages come from our binhost, defined in:
/etc/portage/binrepos.conf/binhost-main.conf
The mode decides how portage uses it:
- user mode:
--getbinpkgonly, only binaries, never compiles - devmode:
--getbinpkg, binaries when they match your configuration, compiles when they don't, and saves what it compiled in/var/cache/binpkgs(FEATURES=buildpkg) - srcmode: compiles everything
If you have your own binhost (for example a second machine that compiles for you), add it in its own file, like /etc/portage/binrepos.conf/100-my-binhost.conf, with its own priority. See the Gentoo binary package guide for the format.
Profile
Argent uses the Gentoo profile:
default/linux/amd64/23.0/desktop/plasma/systemd
avasile sets it at every mode switch, and our binaries are built for it. You can see it with:
eselect profile show
You can change it with eselect profile set, as on any Gentoo, but then your system no longer matches the binhost, and the next avasile mode switch sets it back.
On top of the profile, we have our own overrides in /etc/portage/profile/ (use.mask, package.use.mask, package.provided). Those are Argent files too.
Keywords, masks and unmasks
Same as on Gentoo, same rule as for USE flags: your own files, next to ours.
To accept the testing version of a package:
echo "app-editors/neovim ~amd64" >> /etc/portage/package.accept_keywords/100-my.package.keywords
To stop a package (or a version) from being installed:
echo ">=media-video/obs-studio-32" >> /etc/portage/package.mask/100-my.package.mask
To allow something that we masked:
echo "=media-video/obs-studio-32.0.1" >> /etc/portage/package.unmask/100-my.package.unmask
Before you unmask anything of ours, look in /etc/portage/package.mask/00-*.package.mask why we masked it, there is usually a comment. In user mode, an unmasked or keyworded version that is not on our binhost can't be installed.
Per package environment
/etc/portage/package.env/ together with /etc/portage/env/ lets you compile some packages with different settings (CFLAGS, FEATURES, MAKEOPTS, ...). We use it for a few packages already, see /etc/portage/package.env/00-argent.package.env. The Gentoo documentation for it is here.
Your own, for example to compile a big package with fewer jobs:
echo 'MAKEOPTS="-j2"' > /etc/portage/env/100-my-lowjobs.conf
echo "www-client/chromium 100-my-lowjobs.conf" >> /etc/portage/package.env/100-my.package.env
This only matters when a package gets compiled, so devmode or srcmode.
Sets
Argent ships its own package sets in /etc/portage/sets/: @basesystem, @plasma-full, @plasma-tools, @multimedia, @tools and so on. To see what is in one:
cat /etc/portage/sets/basesystem
To install one:
epkg install @multimedia
You can make your own set, it's a text file with one package per line. Careful with the name: our set names have no dot, but yours must have one, otherwise epkg update deletes it:
/etc/portage/sets/my.tools
and then:
epkg install @my.tools
The world file
/var/lib/portage/world is the list of packages you asked for. Everything else on your system is there because something in that list needs it.
epkg installadds to itepkg oneshotandepkg recompiledon'tepkg removetakes out of itepkg cleanremoves everything that nothing in it needs anymore
To take a package out of it without removing the package itself (it goes away at the next epkg clean, if nothing else needs it):
emerge --deselect <package>
Keeping your changes in /etc
Portage doesn't overwrites a file in /etc that you changed. When an upgrade brings a new version of a file you edited, portage puts it next to yours as ._cfg0000_<name> and keeps yours. Files you didn't touch are updated instantly.
To see what is waiting:
find /etc -name '._cfg*'
etc-update shows you each one with the differences.
The slight issue: if you take the new version, your changes are gone, and if you keep yours, you miss what the upgrade changed. So leave the package's files alone and put your settings in a separate file that the program also reads. Most programs have a directory for this, a "drop-in" directory, and no package ever installs or overwrites your files there.
| Program | Don't edit | Put your file in |
|---|---|---|
| Apache | /etc/apache2/httpd.conf |
/etc/apache2/vhosts.d/ or /etc/apache2/modules.d/, any name ending in .conf
|
| SSH server | /etc/ssh/sshd_config |
/etc/ssh/sshd_config.d/100-my.conf
|
| SSH client | /etc/ssh/ssh_config |
/etc/ssh/ssh_config.d/100-my.conf
|
| systemd services | /usr/lib/systemd/system/<service>.service |
/etc/systemd/system/<service>.service.d/, see Changing an installed service
|
| systemd settings | /etc/systemd/journald.conf, logind.conf, ... |
/etc/systemd/journald.conf.d/, logind.conf.d/, ...
|
Files in a drop-in directory are read in name order. For Apache and systemd the last value has the highest priority. SSH is reverse logic: the first value has highest priority, and the drop-ins are read before the main file. That's why Gentoo/Argent names its SSH defaults 9999999gentoo*.conf: your 100-my.conf comes first and has highest priority. On older installs, check that sshd_config has the Include line:
grep Include /etc/ssh/sshd_config
Example: Apache
To run a CGI application from /var/www/localhost/bugzilla, create /etc/apache2/vhosts.d/bugzilla.conf:
<Directory "/var/www/localhost/bugzilla"> AddHandler cgi-script .cgi Options +ExecCGI +FollowSymLinks DirectoryIndex index.cgi index.html AllowOverride All </Directory>
systemctl reload apache2
Files in /etc/conf.d
/etc/conf.d holds the start options of services. It comes from OpenRC, but some Gentoo systemd units still read it. systemctl cat shows you if a service does:
systemctl cat apache2
EnvironmentFile=/etc/conf.d/apache2 ExecStart=/usr/sbin/apache2 $APACHE2_OPTS -DFOREGROUND
/etc/conf.d has no drop-in directory, but the service has one (see Changing an installed service). There are two ways to use it. Both examples add -D PHP to Apache's options.
Method 1: a second settings file
systemctl edit apache2
[Service] EnvironmentFile=/etc/conf.d/apache2.local
and in /etc/conf.d/apache2.local:
APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D SSL -D SSL_DEFAULT_VHOST -D LANGUAGE -D PHP"
The second file replaces the variable, it doesn't add to it. Copy every option from /etc/conf.d/apache2 and add yours. With only APACHE2_OPTS="-D PHP", Apache loses -D DEFAULT_VHOST, which is where Listen 80 is, and refuses to start:
no listening sockets available, shutting down AH00015: Unable to open logs
After an Apache upgrade, compare your file with /etc/conf.d/apache2: if the package changed its default options, your file still overrides them.
Method 2: an extra variable
systemctl edit apache2
[Service] Environment="APACHE2_LOCAL_OPTS=-D PHP" ExecStart= ExecStart=/usr/sbin/apache2 $APACHE2_OPTS $APACHE2_LOCAL_OPTS -DFOREGROUND ExecReload= ExecReload=/usr/sbin/apache2 $APACHE2_OPTS $APACHE2_LOCAL_OPTS -k graceful ExecStop= ExecStop=/usr/sbin/apache2 $APACHE2_OPTS $APACHE2_LOCAL_OPTS -k graceful-stop
The empty ExecStart= clears the package's command before you set yours. The quotes around the Environment= value are needed because of the space. /etc/conf.d/apache2 stays in use, so changes from upgrades still reach you. If an upgrade changes the commands in the unit file, yours hide them: systemctl cat apache2 shows both.
With either method:
systemctl restart apache2