If you followed the previous introduction posts about FreeBSD (here, here, here, here and here) you should already know how to install binary packages. On FreeBSD this is done using pkg, and if you are familiar with apt, dnf, or zypper (or any other package manager on Linux) this should not be a big deal. There is, however, another official way to get additional software onto FreeBSD and this are the so called “ports”. In contrast to the binary packages, ports are source code that comes with all the patches and Makefiles which are required to compile and install a specific piece of program on FreeBSD. Think of it as an automated way of compiling software for FreeBSD.

Depending on how you installed FreeBSD the ports collection might already be there:

root@freebsd14:~ $ ls -l /usr/ports/ | wc -l
      81

If it’s not there, you have a couple of options to get it installed. Either you get it with git (the following will get the HEAD branch, check the link for a description how to checkout a quarterly branch):

root@freebsd14:~ $ pkg install git
root@freebsd14:~ $ git clone --depth 1 https://git.FreeBSD.org/ports.git /usr/ports

… or you get it with portsnap:

root@freebsd14:~ $ mkdir -p /var/db/portsnap
root@freebsd14:~ $ portsnap fetch
root@freebsd14:~ $ portsnap extract

… or you download the the tarball from the website. No matter how you do it, once the ports are available you’ll see something like this:

root@freebsd14:/usr/ports $ pwd
/usr/ports
root@freebsd14:/usr/ports $ ls
.arcconfig      Keywords        accessibility   comms           finance         japanese        net-im          science         x11-clocks
.git            MOVED           arabic          converters      french          java            net-mgmt        security        x11-drivers
.gitignore      Makefile        archivers       databases       ftp             korean          net-p2p         shells          x11-fm
.hooks          Mk              astro           deskutils       games           lang            news            sysutils        x11-fonts
.mailmap        README          audio           devel           german          mail            polish          textproc        x11-servers
CHANGES         Templates       benchmarks      dns             graphics        math            ports-mgmt      ukrainian       x11-themes
CONTRIBUTING.md Tools           biology         editors         hebrew          misc            portuguese      vietnamese      x11-toolkits
COPYRIGHT       UIDs            cad             emulators       hungarian       multimedia      print           www             x11-wm
GIDs            UPDATING        chinese         filesystems     irc             net             russian         x11

Each of those directories is a category, and the categories contain the ports grouped into that category:

root@freebsd14:~ $ ls /usr/ports/databases/
Makefile                                        p5-DBIx-Log4perl                                py-aiosqlite
R-cran-DBI                                      p5-DBIx-MySQLSequence                           py-alembic
R-cran-RMySQL                                   p5-DBIx-NoSQL                                   py-apache-arrow
R-cran-RPostgreSQL                              p5-DBIx-Password                                py-apsw
...
p5-DBIx-Inspector                               py-aiopg                                        xtrabackup84
p5-DBIx-Introspector                            py-aioredis                                     zodb
p5-DBIx-Lite                                    py-aiosql

There are thousands of ports and looking for something in the directory tree might become time consuming. Searching for something can be done with e.g. “whereis“:

root@freebsd14:~ $ whereis puredb
puredb: /usr/ports/databases/puredb

… or you search directly in the ports tree, but before you can do this you need to build the index file:

root@freebsd14:/usr/ports $ make search postgres
The search target requires INDEX-14. Please run make index or make fetchindex.
make: don't know how to make postgres. Stop

make: stopped in /usr/ports

root@freebsd14:/usr/ports $ make index
Generating INDEX-14 - please wait..
 Done.
root@freebsd14:/usr/ports $ 

This created the INDEX file which is used as the source for searches in the tree:

root@freebsd14:/usr/ports $ ls -l INDEX-14 
-rw-r--r--  1 root wheel 48207086 Dec 11 10:13 INDEX-14
root@freebsd14:/usr/ports $ make search name=postgresql | less
Port:   R-cran-RPostgreSQL-0.7.7
Path:   /usr/ports/databases/R-cran-RPostgreSQL
Info:   R Interface to the 'PostgreSQL' Database System
Maint:  [email protected]
...
Port:   databases/postgresql11-pgtcl
Moved:  databases/postgresql12-pgtcl
Date:   2023-12-31
Reason: Has expired: Security support ended on 2023-11-09

The README comes with additional hints and information:

root@freebsd14:/usr/ports $ cat README 
This is the FreeBSD Ports Collection.  For an easy to use
WEB-based interface to it, please see:

        https://ports.FreeBSD.org

For general information on the Ports Collection, please see the
FreeBSD Handbook ports section which is available from:

        https://docs.freebsd.org/en/books/handbook/ports/
                for the latest official version
        or:
        The ports(7) manual page (man ports).

These will explain how to use ports and packages.

If you would like to search for a port, you can do so easily by
saying (in /usr/ports):

        make search name="<name>"
        or:
        make search key="<keyword>"

which will generate a list of all ports matching <name> or <keyword>.
make search also supports wildcards, such as:

        make search name="gtk*"

For information about contributing to FreeBSD ports, please see the Porter's
Handbook, available at:

        https://docs.freebsd.org/en/books/porters-handbook/

NOTE:  This tree will GROW significantly in size during normal usage!
The distribution tar files can and do accumulate in /usr/ports/distfiles,
and the individual ports will also use up lots of space in their work
subdirectories unless you remember to "make clean" after you're done
building a given port.  /usr/ports/distfiles can also be periodically
cleaned without ill-effect.

Lets say we want to install PostgreSQL 17, what do we need to do. Actually this is quite easy. First, enter the ports directory:

root@freebsd14:/usr/ports $ cd databases/postgresql17-server/
root@freebsd14:/usr/ports/databases/postgresql17-server $

If you’re curious, have a look at the Makefile to see what will happen, otherwise just install the port (“clean” will cleanup afterwards to save space on disk):

root@freebsd14:/usr/ports/databases/postgresql17-server $ make install clean

This will bring up a new windows which gives you some options to either enable or disable:

Once you’re happy with it, let it build and install. This will start downloading the PostgreSQL sources and then ask for options for bison:

This goes on for all the tools required to build PostgreSQL:

… (and so on) and finally you’ll see the usual “configure” and “make” stuff on the screen (this will run the regression tests as well, so expect it to take some time). If you just want to get a feeling about ports, maybe don’t chose PostgreSQL as your first port, because this really takes time as all the dependencies (llvm, …, ) get build from source as well.

Once it is done you’ll find the binaries in “/usr/local/bin/”:

root@freebsd14:/usr/ports/databases/postgresql17-server $ ls /usr/local/bin/pg*
/usr/local/bin/pg_amcheck               /usr/local/bin/pg_ctl                   /usr/local/bin/pg_restore
/usr/local/bin/pg_archivecleanup        /usr/local/bin/pg_dump                  /usr/local/bin/pg_rewind
/usr/local/bin/pg_basebackup            /usr/local/bin/pg_dumpall               /usr/local/bin/pg_test_fsync
/usr/local/bin/pg_checksums             /usr/local/bin/pg_isready               /usr/local/bin/pg_test_timing
/usr/local/bin/pg_config                /usr/local/bin/pg_receivewal            /usr/local/bin/pg_upgrade
/usr/local/bin/pg_controldata           /usr/local/bin/pg_recvlogical           /usr/local/bin/pg_waldump
/usr/local/bin/pg_createsubscriber      /usr/local/bin/pg_resetwal              /usr/local/bin/pgbench
root@freebsd14:/usr/ports/databases/postgresql17-server $ /usr/local/bin/psql --version
psql (PostgreSQL) 17.2

All the question which have been answered can also be given on the command line to automate the whole process (‘-‘ means do not include, ‘+’ means include):

root@freebsd14:/usr/ports/databases/postgresql17-server $ make pretty-print-config
-DEBUG +DOCS -DTRACE -GSSAPI -LDAP +LLVM +LZ4 +NLS -OPTIMIZED_CFLAGS -PAM +SSL -TZDATA +XML +ZSTD 

A more verbose description of those can be shown like this:

root@freebsd14:/usr/ports/databases/postgresql17-server $ make showconfig
===> The following configuration options are available for postgresql17-server-17.2:
     DEBUG=off: Build with debugging support
     DOCS=on: Build and/or install documentation
     DTRACE=off: Build with DTrace probes
     GSSAPI=off: Build with GSSAPI support
     LDAP=off: Build with LDAP authentication support
     LLVM=on: Build with support for JIT-compiling expressions
     LZ4=on: Build with LZ4 compression support
     NLS=on: Use internationalized messages
     OPTIMIZED_CFLAGS=off: Builds with compiler optimizations (-O3)
     PAM=off: Build with PAM Support
     SSL=on: Build with OpenSSL support
     TZDATA=off: Use internal timezone database
     XML=on: Build with XML data type
     ZSTD=on: Build with ZSTD compression support
===> Use 'make config' to modify these settings

To summarize: A lot of additional stuff is available in the ports collection. If something is not available as a package, have a look there.

If you want to see what’s going in the ports collection, have a look at FreshPorts.