Jump to content

Enhancing Security and Efficiency in ProcessWire Installations


AswinC
 Share

Recommended Posts

Hello everyone,

As a community that frequently installs ProcessWire, we understand the importance of efficiency and security in our workflows.
We’ve been contemplating the idea of leveraging auto-deploy scripts to streamline our installations, especially considering the wide array of web hosting panels available to us.

Here’s a rough sketch of how we envision this process:

  1. Git clone: The first step would involve cloning the repository.
  2. Pre-configuration: Next, we’d place an install_preconfig.php file containing an array of variables that install.php could utilize if available. This file would include pre-configured variables such as dbhost, among others.
  3. Auto Install Modules
  4. Cleanup. Deleting the pre-config file & installation file.

Currently, we’re aware that these variables are fetched using ini_get, which unfortunately poses a security risk.
If someone were to launch phpinfo(), our credentials could potentially be exposed.

To mitigate this, we propose replacing all variables in the install file with $preconfig['mysqli.default_host'] ?? ini_get("mysqli.default_host"). This way, we prioritize the use of our pre-configured variables, resorting to ini_get only when necessary.

We believe this initiative could significantly enhance both the security and efficiency of our ProcessWire installations.
However, we understand that this is a community effort.
What is the best way to get this initiative hit off?  @ryan

Kind Regards,

Link to comment
Share on other sites

  • AswinC changed the title to Enhancing Security and Efficiency in ProcessWire Installations

It's been talked about elsewhere here in the forums, but an alternate idea would be utilizing .env files. It would satisfy both the installation process and long-term management of values. Some benefits:

  • Widely used across applications, frameworks, and languages running in a web server environment and strongly recommended as a standard practice
  • Secure by default. Web servers do not serve .env files
  • Provides the ability to manage local and production configurations separately
  • Frameworks like Laravel provide a .env file as well as a .env.example file containing all variables used in the application. This is kept up to date, used to document application requirements, and is committed into the repository
  • Values that are not security-critical can be safely stored in the example file
  • Provides a convenient location for additional non-ProcessWire site/app specific values such as API keys, or those required for modules
  • Solves the issue of excluding site/config.php from a repository given that it's a required file containing specific syntax and $config object property assignments

If .env was available in ProcessWire I would have my Fluency module look for translation API keys there rather than store them in the database. A benefit there is that different environments like local/ staging/production can mean an environment that is yours and an environment that is a client's. Pulling the latest copy of a database from production wouldn't require manually re-configuring modules that require API keys, or module registration keys.

It would be good to eliminate storing security-critical values in PHP files entirely. The .env file could be generated and populated during the ProcessWire install process pre-excluded in the .gitignore file. Example:

ENVIRONMENT="development"

# ProcessWire
PW_DB_HOST=localhost
PW_DB_NAME="your_database
PW_DB_USER=your_database_user
PW_DB_PASS="LowuHeju7[BoI3"
PW_DB_PORT=3306
PW_DB_ENGINE=InnoDB
PW_DEBUG=true
PW_CHMOD_DIR=0755
PW_CHMOD_FILE=0644
PW_USE_PAGE_CLASSES=true
PW_USE_FUNCTIONS_API=true
PW_PREPEND_TEMPLATE_FILE="_init.php"
PW_USER_AUTH_SALT=d5e3ac4beda1e382255bbd8744d7e815
PW_LOCALE="en_US.UTF-8"
PW_TIMEZONE="America/Los_Angeles"
PW_DEFAULT_ADMIN_THEME=AdminThemeUikit
PW_INSTALLED=1580675413
PW_HTTP_HOSTS = "domain.com,www.domain.com"

# Some API that is used
EXTERNAL_SERVICE_API_URL="https://api.someservice.loc/v2" # Development
EXTERNAL_SERVICE_API_KEY=0d41fe1b68244f4ea51ae5e4abd24fab

# Mailgun
MG_KEY=key-192cde47ab73095e747ebe7556577b2d
MG_DOMAIN="mg.somedomain.com"

# Forecast.io
FORECAST_IO_KEY=c28096383d66bcb1e2cb9ec37153f85c

To take the idea further, it could be integrated with the ProcessWire API in a way that would prevent conflicts, keep .env variable naming organized, and make any value added by the developer available. Something like:

<?php

// An accessor method, this is probably the cleanest and resembles other frameworks
$config->env('SOME_ENV_VARIABLE');

// Nested under a property acting as a namespace
$config->env->SOME_ENV_VARIABLE;

// On ProcessWire projects I implement some extras to easily interact with .env values without needing to access them directly.
$config->envIs('production'); // boolean

I haven't built a ProcessWire site without implementing this for many years and there's a great widely-used great package that provides .env values to PHP. There are also hosting providers that make environment variables/secrets manageable through their admin UI that eliminates the need for an actual file in production entirely. If ProcessWire were to implement environment variables it could look to values that may already exist and fall back to using a file.

Implementation aside, if someone is able to access phpinfo() in production it's a critical issue beyond exposing config values given the totality of information dumped by that function.

  • Like 8
Link to comment
Share on other sites

18 hours ago, FireWire said:

I haven't built a ProcessWire site without implementing this for many years

Me too! This is now default in all my installations for all the reasons you mention.

But I feel this sort of update would be a PW4 thing? 

  • Like 1
Link to comment
Share on other sites

On 4/23/2024 at 8:20 AM, elabx said:

But I feel this sort of update would be a PW4 thing? 

I didn't think about that, but it could be. I don't want to make assumptions about ease of implementation. Breaking changes could be mitigated with fallbacks- use the env if it's available, and fall back to config object if not. I think what would be a true PW4 change would be full adoption of .env and deprecation of config.php. A case could be made that fallbacks now can introduce gradual adoption and make a breaking change in PW4 less impactful.

On 4/22/2024 at 1:57 PM, gmclelland said:

Here's one place this was talked about in the past:

I hadn't seen this discussed there in a formal repo thread before, but good to see interest elsewhere. IMHO, the initial framing of the request around 12 factor apps could have been simplified to just benefits and good practice. Conversely, the argument that not everyone is building 12 factor apps isn't a case against it. All said- I don't want to be critical of a conversation that happened that long ago, I mean- who would I be to talk? I wasn't using .env files in 2017 🤷‍♂️

I do want to share a thought on this specifically in ProcessWire context. One of my favorite things about PW is the file structure philosophy where core lives in /wire and templates, styles, additional modules, assets, etc. live in /site. Site is a living breathing volatile folder and the domain of the developer to extend ProcessWire as a project demands. Replacing /wire is one of the most frictionless upgrade concepts ever and it's flat out elegant. It would be great to see the /site folder adopt that- a true "drag-and-drop" self-contained application directory that can be deployed anywhere ProcessWire exists. The /wire directory wouldn't be dependent on /site, and (aside from core version) /site wouldn't be coupled to /wire. Consider that the root directory is already environment specific. The .htaccess file, node_modules, vendor, .git, etc. are all in environment context. The use of .env fits here. This may come off as an esoteric or abstract argument, but think about how much time you spend naming things in programming and tell me that's not the world we live in 🤣

To address a point in that Github thread as to considerations made inside /site for environment, such as an 'if' statement whether on dev or production, I think that's great for application logic that responds to the environment but does not alter it.

It would be great to see this adopted into core, but as always with a project like ProcessWire it's up to the people doing the great work of maintaining and improving it to determine priority. Even if it's not implemented in core, I hope to have made a case for adoption in individual projects.

Link to comment
Share on other sites

@ryan, Can you have a look at this, and point us into the direction how to get this into pw3 / pw4 ?
Being supported /maintained by the community.
Basically an auto install by providing a preconfig or .env variables.

Link to comment
Share on other sites

  • 3 weeks later...

I've been running processwire locally with the vendor/ folder up one level, outside the site root. Check out Moritz' post on processwire.dev for the background to this. This works fine, but requires a few tweaks. I can't find the post at the moment, but I do remember reading that Ryan has said that he considers the /index.php file as site-specific and therefore can be edited by users for their specific installations. So I've chosen to edit the vendor/ path directly in /index.php for testing.

I've also been experimenting with allowing the installation to define the vendor/ path via an environment variable, and this seems to work well, too. I've put in a speculative pull request for this.

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   1 member

×
×
  • Create New...