# Building pfSense from Source and Contributing

> Building pfSense from source code, development environment setup, repository structure, System Patches, gitsync, pull requests, and contributing

Source: https://opennix.org/en/docs/pfsense/development/pfsense-building-from-source/


pfSense CE is an open-source project built on FreeBSD. Its source code is hosted on GitHub across three primary repositories: the base system with the GUI, modified FreeBSD sources, and a ports collection. Developers can build pfSense from source, apply fixes through the System Patches package without a full rebuild, or contribute to the project via pull requests.

## Source Code Repositories

pfSense CE development spans three GitHub repositories:

| Repository | Contents | Purpose |
|---|---|---|
| [pfSense/pfSense](https://github.com/pfsense/pfSense) | GUI code, build scripts | Web interface, PHP logic, utilities |
| [pfSense/FreeBSD-src](https://github.com/pfsense/FreeBSD-src) | OS source code | FreeBSD kernel and base system |
| [pfSense/FreeBSD-ports](https://github.com/pfsense/FreeBSD-ports) | Ports and packages | Build information for software, pfSense packages |

The primary development branch is `master` for the pfSense/pfSense repository and `devel` for FreeBSD-ports. Release branches follow the naming convention `RELENG_2_8_1`.

## Build Environment Requirements

Building pfSense from source requires a FreeBSD-based environment matching the target release version. pfSense uses poudriere for package building and installation image creation.

Minimum requirements:

- FreeBSD matching the target pfSense release (see the [version correspondence table](https://docs.netgate.com/pfsense/en/latest/development/freebsd-version.html))
- Poudriere installed for port building
- Adequate disk space (at least 50 GB for a full build)
- Git for repository management

```bash
# Install required tools on FreeBSD
pkg install git poudriere
```

## Repository Structure

The pfSense/pfSense repository is organized as follows:

- `src/` - PHP files for the web interface, configuration scripts
- `tools/` - build scripts and developer utilities
- `src/etc/inc/` - core PHP modules (config.inc, util.inc, interfaces.inc)
- `src/usr/local/www/` - web interface pages
- `src/etc/phpshellskel/` - PHP Shell scripts

## Building from Source

The process for building pfSense CE from source:

```bash
# Clone the main repository
git clone https://github.com/pfsense/pfSense.git
cd pfSense

# Switch to the desired branch (e.g., RELENG_2_8_1)
git checkout RELENG_2_8_1

# Start the build (requires a configured poudriere environment)
./build.sh
```

A full build compiles the FreeBSD kernel, builds all ports via poudriere, and produces an installation ISO image. The process is time-consuming and requires proper environment configuration.

## System Patches - Fixes Without Rebuilding

The System Patches package allows applying corrections to pfSense without a full system rebuild. Patches can be obtained from the official repository, pasted in manually, or uploaded from external sources.

### Installation

Install the package via **System > Package Manager > Available Packages** by searching for `System Patches`.

### Usage

Once installed, the package is accessible at **System > Patches**. It provides:

- Fetching recommended patches from Netgate with auto-apply capability
- Adding custom patches from URLs, pasted text, or uploaded files
- Applying and reverting patches through the web interface
- Testing fixes from pull requests before they are merged into a release

System Patches is particularly useful for validating GitHub pull request fixes before upgrading to the next pfSense version.

## gitsync - Updating Between Snapshots

The gitsync utility synchronizes PHP code from the pfSense CE Git repository, enabling developers to receive fixes between official releases without installing a new snapshot.

### Limitations

- Works only with pfSense CE; not compatible with pfSense Plus
- Synchronizes PHP files only - binary changes are not applied
- Some PHP changes require corresponding binary updates available only through a full snapshot
- Recommended for use only when directed by developers or when the user closely follows development activity

### Running gitsync

From the pfSense console menu, select option 12 (developer shell):

```
> playback gitsync master
```

Or from the standard shell (console option 8):

```bash
pfSsh.php playback gitsync master
```

To synchronize with a specific release branch, replace `master` with the branch name:

```bash
pfSsh.php playback gitsync RELENG_2_8_1
```

If Git is not installed, add it manually:

```bash
pkg install git
```

If errors occur due to repository URL changes, remove the old clone:

```bash
rm -rf /root/pfsense/
pfSsh.php playback gitsync master
```

## Submitting Pull Requests

To contribute changes to pfSense CE via GitHub:

1. Create an issue entry in [pfSense Redmine](https://redmine.pfsense.org) for the bug or feature (minor typo fixes are exempt)
2. Fork the appropriate repository:
   - `pfSense/pfSense` - for base system and GUI changes
   - `pfSense/FreeBSD-ports` - for package changes
3. Make changes in the correct branch:
   - `master` - for pfSense/pfSense
   - `devel` - for FreeBSD-ports
4. Reference the Redmine ticket number in your commit message
5. Create a pull request with a description and a link to the Redmine entry
6. Add the PR link to the corresponding Redmine issue

Pull requests can be tested on a live system using the System Patches package before they are accepted into the main branch.

## Developer Style Guide

pfSense follows the K&R BSD KNF coding style. Key rules:

### Formatting

- Tabs for indentation (8-stop width); spaces are not permitted
- Braces are mandatory for all `if`, `for`, and `foreach` blocks, even single-line ones
- Space between keywords and parentheses (`if (`, `foreach (`), but not between function names and arguments (`function_name(`)
- No trailing whitespace on any line

### PHP Conventions

- Variable names in lowercase with underscores (`$my_variable`) or camelCase (`$myVariable`)
- Never use `$g` as a loop variable - it conflicts with the pfSense global `$g`
- Use `elseif` instead of `else if` for compatibility with PHP alternative syntax
- Do not use deprecated PHP functions

### Security

- Minimize shell command execution; when necessary, use `escapeshellarg()` for variables
- Always escape user input with `htmlspecialchars()` when rendering output
- Follow MVC principles: separate display logic from validation and storage logic

### Comments

- Use `//` or `/* */` syntax, written in English
- Labels: `TODO:` for planned work, `FIXME:` for known issues, `NOTE:` for important clarifications

## PHP 8.x Considerations

pfSense has migrated to PHP 8.x, which introduces several requirements for developers:

- Strict typing: implicit type coercions generate warnings
- Removed functions: `each()`, `create_function()`, and `mysql_*` are no longer available
- Named arguments: function parameter names must maintain backward compatibility
- Use `elseif` instead of `else if` - the latter does not work correctly with alternative syntax

Verify code compatibility with the target PHP version before submitting a pull request.

## Debug Kernel

For diagnosing kernel-level issues, pfSense provides a package with debug symbols:

```bash
pkg install pfSense-kernel-debug
```

The debug kernel includes symbols needed for analyzing core dumps and kernel tracing. Use it when reproducing a kernel panic or preparing a bug report related to kernel behavior.

## FreeBSD Issue Policy

pfSense is based on FreeBSD, and certain issues belong to the FreeBSD base system rather than pfSense itself. When encountering a bug related to the kernel, drivers, or FreeBSD base utilities:

- Verify whether the issue reproduces on a clean FreeBSD installation of the corresponding version
- If it reproduces on FreeBSD, report it to the [FreeBSD bug tracker](https://bugs.freebsd.org/)
- If the issue is pfSense-specific, create an entry in pfSense Redmine

Netgate developers do not fix issues in the FreeBSD base system, except for critical security vulnerabilities.

## Reporting Bugs and Requesting Features

### Reporting Bugs

To report a bug in pfSense:

1. Check whether the issue already exists in [pfSense Redmine](https://redmine.pfsense.org)
2. Gather diagnostic information (pfSense version, FreeBSD version, logs)
3. Create a new entry with a detailed description: reproduction steps, expected behavior, and actual behavior
4. Attach screenshots, logs, and panic information if applicable

### Requesting Features

Feature requests are also created in Redmine. Describe the proposed functionality, its justification, and potential implementation approaches. Technical development questions can be discussed on the [Netgate Forum](https://forum.netgate.com).

## Related Sections

- [Package Development](/docs/pfsense/development/pfsense-package-development/) - creating custom packages, port structure, XML manifest
- [Custom Scripts](/docs/pfsense/development/pfsense-custom-scripts/) - automation scripts, Shellcmd, and Cron
- [API and Automation](/docs/pfsense/development/pfsense-api-automation/) - programmatic management via REST API

