# fortrabbit blog > Official fortrabbit company blog with announcements, product updates, tutorials, and community stories. --- # 10 pillars of modern PHP development Source: https://blog.fortrabbit.com/10-pillars-php-dev Created: 2015-06-04 Author: Ulrich Kautz Tags: webdev > Ten principles of modern PHP application design, from dependency management to deployment, as we apply them on our own hosting platform. ## PHP development then and now For most of us PHP developers writing applications now compared to ten or so years ago is quite a different endeavor. Back then, many of us were rather web designers; responsible not only for backend development, but database engineering, system administration, frontend programming and maybe conceiving and designing the very UI as well. This has changed in recent years. Classical web sites are becoming more and more the domain of specialized SaaS - why write another blog engine, cooperate homepage CMS or small time ecommerce system if there are already so many available for (nearly) free? Or to put it the other way around: everything which can be easily automated (CMS, blog, ..) will be eventually. What cannot needs to be custom made. So web developers changed themselves by specializing and concentrating on what cannot be automated so easily: web applications. Along with this came a new mindset on how PHP development should be done and what tools should be used. We often receive requests on how to design applications for our [hosting infrastructure](http://www.fortrabbit.com). While there are a thousand different use-cases, many deserving of a different approach, the following is based on our experience and should be viewed as a guideline. Many people are using modern full stack frameworks, such as [Laravel 5](http://laravel.com/), [CakePHP 3](http://cakephp.org/), [Symfony 2](https://symfony.com/) or the like. Those already come with a set of style guides, patterns and recommendations. However much is still up to the developer so here are our two cents on how a current PHP application development should be approached. ## 1. Code The most important part of your application. ### Management The code should be under version control. We go a step further and strongly recommend Git due to it's wide spread and availability across the board (and because we are not aware of truly superior alternatives). ### Style Adhering to [defined coding standards](http://www.phptherightway.com/#code_style_guide) will pay out: consistent code is [better comprehendable](http://www.cs.loyola.edu/~binkley/papers/tr-loy110720.pdf) by other members of a team and thereby adding new members is easier. No matter the size of the team (even for single developers): code maintenance can easily take up the [majority of a projects time](http://www.sersc.org/journals/IJSEIA/vol7_no5_2013/36.pdf) (thus money) and well formatted and documented code is the [primary factor](http://stackoverflow.com/a/1325617) in reducing those efforts. Also it's just plain satisfying to read good code. ### Open sourcing Open sourcing your application code (or at least modularized parts of it) can be an extremely good idea: free hands to harden the code quality, free marketing for yourself or your company and supporting the community as a whole. Again, we'd like to put an emphasis on Git. Using an exotic revision control it could be hard to find developers which are willing to spare the extra time. The before mentioned style will also impact the level of acceptance and willingness to participate: using existing standards helps allows newcomers to jump right in without wasting time on deciphering your intentions. ## 2. Tests Automated testing has long been the black sheep of the PHP family. However, this has greatly changed; the legend it would double development time is nearly rooted out and it's now (luckily and) virtually unthinkable to contribute anything to most open source projects without a corresponding test. A thoroughly [tested application](http://en.wikipedia.org/wiki/Software_testing#Testing_levels) brings a lot of advantages. My personal top three: - Tested software can be far easier refactored - Unit testing enforces modular design (increased re-usability) - Tests provide a documentation and example code There are lots of [benefits](http://en.wikipedia.org/wiki/Unit_testing#Benefits) but in the end for me it boils down to this: Better code — less headache. ## 3. Dependencies Dependencies should (of course) be handled with [Composer](https://getcomposer.org). Since the code is strongly coupled with specific package/library the dependency declaration (`composer.lock`) should be in the version control as well (in my opinion). The actual package/library files (`vendor` folder) should not be part of version control, since their revisions are already handled by the declaration, which is thereby under version control and it would be redundant to do both. ### Modularization Being a user of libraries/packages also changes your mindset (or at least positively re-enforces it) towards modularization of your own code. This in turn leads to less code repetition across projects and thereby reduces effort and increases quality in the long term. And let's not forget the ability to open source those modules, as mentioned above. ## 4. Configuration Configuration, if badly used, can be a great hindrance when migrating your application. More so, it can be a security risk. ### Separate config from code Using the environment is definitely the best choice. By this we primarily mean (operating system) environment variables but we think local configuration files (or a combination thereof) are a valid choice as well - as long as their deployment is clearly defined. The best rule of thumb to measure whether the configuration is cleanly separated from the code we heard is: Could you open source your code without exposing any credentials right now? If the answer is Yes, then you are good. **Bad**: in some `config.inc.php`: ```php $database = "foobar"; $user = "foobar"; $password = "foobar"; ``` **Good**: Environment variables from Apache `SetEnv` or the like: ```php // $_SERVER["DB_NAME"]; // $_SERVER["DB_USER"]; // $_SERVER["DB_PASSWORD"]; ``` ### Complex config Environment variables can contain complex information (think: multi level array). It should be marshaled as JSON and encoded into base 64 so it is easily modifiable and readable from outside the application. ```php // somewhere in the bootstrap, assuming all encoded variables are prefixed with "::".. foreach ($_SERVER as $k => $v) { if (0 === strpos($v, "::")) { $_SERVER[$k] = json_decode(base64_decode(substr($v, 2))); } } ``` ## 5. Assets Asset data, such as (compiled) CSS, JavaScript, images and so on, are truly hard to decide upon. In short - and with limitations - my recommendation is to keep them under version control. At length: Compilation of CSS and JavaScript or creating modified instances of images requires a surprisingly large and diverse tool set which comes with a large dependency set of their own (think c compiler for node extension which shrinks images using image magick bindings vs complete Java runtime for some CSS compilers vs ..). This increases the complexity of the deployment infrastructure unnecessarily. Then there is the responsibility problem: Assets are often handled by the frontend developers of the team. As all specialized developers, they have their tools which work great for them. Forcing asset compilation in the release cycle means they need to limit themselves to the tools available here. For a truly in-depth discussion about this topic please see [Frank's previous article](/i-love-assets). ## 6. Runtime data Runtime data includes all file based data (i.e. no databases), which is generated at runtime by user interaction (eg file uploads) or as an result thereof (eg multiple instances of an image). Classically this is handled using a local or network attached file system (see also [flysystem](https://github.com/thephpleague/flysystem)). We recommend cloud storages (such as [S3](http://aws.amazon.com/s3/), [Cloud Files](http://www.rackspace.com/cloud/files), [Cloud Storage](https://cloud.google.com/storage/docs/overview), ..), since they: inherently solve various scalability issues (scaling application out over multiple servers or geographical regions), prevent future migration headaches (data lock-in), natively balance load by separating execution (PHP scripts) and delivery (static files). ## 7. Resources Resources are all services which are used by the application, such as databases, caches, queues, the afore mentioned storages, mail delivery providers and all that. ### Abstraction Access to resources should be abstracted. The degree of abstraction should depend on probability (eg if you are planing to scale out then you'd use an adapter for a local resource, which later will be replaced by an adapter for a network capable resource) and feasibility (eg a cache abstraction is almost always simple, while an abstraction allowing to substitute a MySQL database with, say, ElasticSearch much more effort, eg using the [repository pattern](http://code.tutsplus.com/tutorials/the-repository-design-pattern--net-35804), and this effort must be justifiable). The location of resources must be substitutable by configuration (as described above). **Bad**: ```php $conn = new mysqli($servername, $username, $password); ``` The code will be tightly coupled to MySQL databases with a specific driver. If either MySQL databases or this driver is not available in a new environment the code must be refactored. **Good**: ```php use Illuminate\Database\Capsule\Manager; // $_SERVER['DATABASE'] = ["host" => "localhost", ...] $mgr = new Manager->addConnection($_SERVER['DATABASE']); ``` Using a different SQL database can easily be achieved. Using a different MySQL database location can be easily configured. ### Weak coupling All "soft" services, without which the application still can run (eg a database driven application could not run without the database) should be disengageable easily. Say a mail service is used to greet new users with a welcome mail: make sure you can switch it off with with a single command, in case the mail provider temporarily goes down. Even better: automate that. Best: Use a queue which can back-off and retry by itself. ## 8. Deployment In a web application project, there are few things more feared, more disaster prone and hence over and over delayed than big upgrades into production. [Deploy early and deploy often](http://programmer.97things.oreilly.com/wiki/index.php/Deploy_Early_and_Often) circumvents this by continuous integration of small upgrades. The primary requirement to allow this is a simple, transparent and fast deployment. We are huge fans of Git based deployment, since it already comes with a history and allows easy integration of build scripts. However, application needs and environments differ greatly, so the perfect deployment for all situations is probably not to find. Good code quality, testing and good measured abstraction pay out in the long run, having a easy to use deployment workflow is essential for the day in, day out work. ## 9. Stages While automated testing provides a good foundation, when code meets content there is still lot's of room for mishaps. Hence there is the concept of staging. Having a (working) local setup of the application already provides the first stage: the _development stage_ (or _local stage_). The other stage, which always exists, is of course the _production stage_: the live web application. Now there is lot's of space in between for testing, review and whatnot. In general, all stages should try to approximate the production environment as closely as possible. The more they deviate, the less sense they make. How many stages should be used depends on project size, team size, team setup, kind of application and so on. Please read a [more comprehensive discussion here](/multi-stage-deployment-for-website-development). As a general rule of thumb we recommend three stages: A local development stage, of course the production stage and a testing stage in the same environment as production (of course: separated). ## 10. Scalability You probably have heard that you are now a [DevOp](http://en.wikipedia.org/wiki/DevOps). This means: when writing your application, you must be aware of the underlying infrastructure so you don't fight with it's weaknesses, but rather leverage it's strength. It's a bit of a side effect of the cloud infrastructure. Before: all you had to do (and often could do) was vertically scaling your machine: bigger server. So you would not care as much where the bottle neck was, since there was only one solution. Now that you can not only scale out (horizontally), but do that for every resource individually, you should know which one slows you down. Or what you can do in terms of application design to compensate for that. Or especially: which new resource you can attach to boost the performance. In short: You got access to the red button and with great power comes great responsibility. ## Summary **It's harder now**: You must know more about coding patterns, deployment strategies, testing and application design than ever before. **It's easier now:** a fleet of new tools, better services and coding standards help and support as never before. > The art of writing PHP code has changed. A lot. And we think it's now more interesting than ever. ## Further readings When writing about modern application development in the cloud, one must mention the [12-factor App](http://12factor.net/) by Adam Wiggins. It lays out the complete design and life-cycle of a modern application. Corey McMahon wrote up a great three part series on how to apply (as close as possible) the 12-factor draft [here](http://slashnode.com/the-12-factor-php-app-part-1/). From a pure PHP point of view, I can subscribe to the abstract ideas, but not to (all) of their concrete approaches. In addition, I think the scope of their document overreaches what should be the concern of a developer. # 1,000 developers Source: https://blog.fortrabbit.com/1000-developers Created: 2013-02-19 Author: Oliver Stark Tags: chronicles > Our first 4 digits number! Thank you for your interest in our service! The counter of total accounts changed today from 3 to 4 digits - we are very excited. 1,000 PHP developers signed up, confirmed their email, created Apps and deployed code. The majority of you explored our platform during the last 6 weeks. We belief 1,000 is just a fraction - there are zillions of other developers who never heard about us. For us, 3 guys with a simple idea of better platform for PHP developers, this tiny number and your feedback shows that there was something missing in the current PaaS-World. It shows we are on the right way, with the right tools and the right attitude to make make it big. A big THANK YOU goes out to Bruno Skvorc and Gabriel Manricks. They mentioned us in their articles at [phpmaster.com](http://phpmaster.com/php-as-a-service-fortrabbit/) and [net.tutsplus.com](http://net.tutsplus.com/tutorials/setting-up-a-staging-environment/) # 20 years Pretty Home Pages Source: https://blog.fortrabbit.com/20-years-pretty-home-pages Created: 2014-05-28 Author: Frank Lämmer Tags: opinion > PHP turned twenty. An infographic through the history of the language that still powers most of the pretty home pages on the web. We don't know the exact date, maybe there is none, maybe it's not really important at all. But i think it's notable that the web programming language for pretty homepages is already 20 years old. A lot of people hate PHP, some take it seriously, we love it. ![php-history-infographic](/images/php-history-infographic.png) Credit should go to the really nice [history of PHP](https://github.com/open-source-museum/the-history-of-php) project by Yusuke Ando and Tsutomu Kawamura. This is actually just a remix. Is there an error or something important missing? Please tell us! # Updates Source: https://blog.fortrabbit.com/2014-03-13-changelog Created: 2014-03-13 Author: Ulrich Kautz Tags: changelog > Platform changelog for 13 March 2014: PHP 5.4.26, plus pre-deploy commands and Composer prefer-source in the deployment file. * PHP: 5.4 -> 5.4.26 * Added `pre-deploy` and Composer's `--prefer-source` to Deployment file # Updates Source: https://blog.fortrabbit.com/2014-03-30-changelog Created: 2014-03-30 Author: Ulrich Kautz Tags: changelog > Platform changelog for 30 March 2014: PHP 5.4.26 and PHP 5.5.10 on the stacks, and a Phalcon update to version 1.3.2. * PHP: 5.4.25 -> 5.4.26 * PHP: 5.5.9 -> 5.5.10 * Phalcon update 1.3.2 # Updates Source: https://blog.fortrabbit.com/2014-04-14-changelog Created: 2014-04-14 Author: Ulrich Kautz Tags: changelog > Platform changelog for 14 April 2014: PHP 5.4.27 and 5.5, updated Memcached and MongoDB extensions, and ZSH available over SSH. * PHP: 5.4.26 -> 5.4.27 * PHP: 5.5.10 -> 5.5. * Memcached extension: 2.1.0 -> 2.2 * MongoDB extension: 1.4.5 -> 1.5.1 * ZSH now available on SSH # Updates Source: https://blog.fortrabbit.com/2014-10-24-changelog Created: 2014-10-24 Author: Ulrich Kautz Tags: changelog > Platform changelog for 24 October 2014: PHP updated to 5.4.34 and to 5.5.18 across the fortrabbit hosting stacks. - PHP: 5.4.27 -> 5.4.34 - PHP: 5.5. -> 5.5.18 # Our Drupal 8 install guide took 540 days Source: https://blog.fortrabbit.com/540-days-for-drupal8-install-guide Created: 2016-08-25 Author: Frank Lämmer Tags: chronicles > Why a Drupal 8 install guide took 540 days to write, and what the delay says about writing hosting documentation for a moving target. We maintain a couple of [install guides](https://help.fortrabbit.com/#install-guides) to help our clients to get started with their CMS or framework on our hosting service quickly. So we have some superficial knowledge about modern and popular PHP CMS/frameworks. **Drupal 8 is a huge step forward.** It features modern, object-oriented code (classes, inheritance, interfaces), requires a least PHP 5.5.9, makes use of PHP standards (PSR-4, namespaces, traits), Symfony components, PHPunit integration, Twig, HTML5, Guzzle, Assetic, file system abstraction and more. We were quite exited about Drupal 8, from the first Beta on — as we saw it to be a good fit for our platform. ### Timeline * 2014-10-01 - [Drupal 8 Beta 1 released](https://www.drupal.org/blog/drupal-800-beta-1-released) — yeah! * **2015-02-18** - first draft of our Drupal 8 install guide * 2015-02-15 - [Our first Drupal 8 landing page](https://web.archive.org/web/20150228101028/http://www.fortrabbit.com/drupal-hosting) — in good hope * 2015-08-01 - [Discussion on how to use Composer with Drupal 8](https://www.drupal.org/node/2551607) — hhhm * 2015-10-04 - Clients frequently request Drupal 8 infos — sorry not yet * 2016-03-14 - [Composer issues with Drupal 8 fixed](https://www.drupal.org/node/2648064) - new hope * 2016-04-12 - Problems getting Flysystem to work with [Object Storage](https://help.fortrabbit.com/object-storage) * 2016-05-27 - We submit [a feature request](https://www.drupal.org/node/2735253) to support 3rd party S3 providers * 2016-06-24 - We [ask to help](https://twitter.com/fortrabbit/status/746305157076553728) with the feature request * 2016-07-21 - Our feature requests goes upstream > [drupal 8.1.x-dev](https://www.drupal.org/project/drupal/releases/8.1.x-dev) — Thank you! * **2016-08-03** - We finally release our [Drupal 8 install guide](https://help.fortrabbit.com/install-drupal-8) ### Conclusions There are some differences between CMS and framework install guides. Frameworks are mostly easily to install and configure, CMS are more complex and need more steps to install and tune. Drupal 8 is a huge ecosystem. We have much respect for the community efforts to move it forward to a modern PHP while still taking care about the legacy. Our current version of our Drupal 8 install guide is far from perfect. It's missing tuning tips and a way on how to integrate Memcache. We are thankful for bug reports and contributions (source is on [GitHub](https://github.com/fortrabbit/help/blob/master/docs/install-drupal-8.md)). Thanks again to the Drupalists who helped us come so far. # A Coders Survey Source: https://blog.fortrabbit.com/a-coders-survey Created: 2012-08-21 Author: Frank Lämmer Tags: chronicles, webdev > Results of a survey among developers and designers about hosting, workflows and tools — data that was not available anywhere else in 2012. We have asked everyone interested in a BETA of our upcoming platform a few questions on hosting. That included very valuable feedback for us. Surprisingly we learned that such data was not available on the web. So we have done this little web survey for developers and designers with a wider range (than just hosting). Apply now until and help to make the web a better place (for developers): * [coders-survey.com](http://coders-survey.com/) Results will be published on the 1st of September 2012. This little weekend project is also a little test for our platform as it already runs on it. It features a little simple survey CMS which will be published on [GitHub](https://github.com/fortrabbit/coders-survey) the next days. # About a recent security patch Source: https://blog.fortrabbit.com/about-a-recent-security-patch Created: 2021-03-23 Author: Frank Lämmer Tags: chronicles > The story of one small dashboard security fix: a password form bypassed with browser dev tools, reported by a long-standing researcher. About a week ago our friend and most active security researcher **[Mayank Bhatodra](https://www.mayankbhatodra.com/)** (we have been in contact since 2014) contacted us with a new vulnerability report: > It is possible to bypass the internal password form with our Dashboard by just deleting the input field with the browser developer tools and then sending the form without that input. ## Proof of concept This video shows the issue in action: ## Some explanation of the issue This is not the login form. This is a form which asks the user to enter their password when they want to perform a critical action within the Dashboard while being logged in. There are many critical actions that can be done in our Dashboard, like deleting websites. So we have something called "SUDO mode", where you will only have to enter the password every 30 minutes by default. This setting can be changed. The issue reported by Mayank is about that SUDO form. When 2FA is enabled an additional 2FA field is shown as well with any SUDO action. We have been able to reproduce the issue. It was however not possible to send an empty form or a false password. The issue is embarrassing and stupid. And it must have been around for years. We did not consider it to be of critical severity, but for sure it's something that needed to be fixed. ## My experience working with pentesting security researchers We are contacted by freelance security researchers on a regular basis. We don't have a bug bounty program in place. Here is our vulnerability reporting page: [fortrabbit.com/vulnerability-reporting](https://www.fortrabbit.com/vulnerability-reporting). We like to support the idea of responsible disclosure of white hat hackers. Reality is less idealistic. Often reports are just following standard text book procedures to be applied for any website. Trivial things are getting reported as major issues over and over again. I don't see a big issue with embedding our marketing page in an iframe. However, we always endeavour to check, discuss and answer in a timely manner. All security researchers we have had contact with are from South Asia. I like this kind of global exchange. Our marketing website and the Dashboard are just one level of interaction. We offer access to our PHP hosting services on various protocols and even provide SSH access. I would like to see some more serious and more deep level kind of penetration testing here. ## Why we're publishing this We believe that disclosure of security vulnerabilities will help to increase security in general, as [pointed out by Mr. Schneier over here](https://www.schneier.com/essays/archives/2007/01/schneier_full_disclo.html) - although we might always find the time to publish such reports. I also want to highlight that we are actively maintaining our hosting platform. Over the past years we have been slow to publish big client-facing new features. Please be assured, we are here - working on the platform and we do have some bigger things in planning as well. We are human and sometimes we make stupid mistakes like this. We accept that and we are eager to learn and correct them. # Online text editors Source: https://blog.fortrabbit.com/about-new-online-text-editors Created: 2012-08-07 Author: Frank Lämmer Tags: opinion, webdev > A first look at browser-based code editors and web IDEs in 2012 — what the category promised, and whether it was any good yet. **tl;dr** Just a quick intro to a new category of upcoming online code editors.\*\* The web is moving forward. The browser is the ultimate killer app. With new HTML5 technologies and some JavaScript magic one can do really sophisticated applications in it. You can DO things in the browser. Why open a desktop word processor, when you can open just another tab? We see that online code sharing, debugging tools like: [JSfiddle](http://jsfiddle.net/), [JSBin](http://jsbin.com/), [Dabblet](http://dabblet.com/), [CSSDeck](http://cssdeck.com/), [jsdoit](http://jsdo.it/), [Gist](https://gist.github.com/) are rising. Where is the browser based full featured text editor for code and markup, the thin IDE? The idea is not so new. Did you know that Heroku started with [code in the cloud](http://www.flourish.org/blog/?p=687), an online text editor? The Coding Monkeys created [SubEtha](http://www.codingmonkeys.de/subethaengine/) (and SubEthaEdit) in 2003. But here are three promising startups (of course all from the valley) willing to fill this gap: - **[action.io](http://action.io)** > [on RWW](http://www.readwriteweb.com/hack/2012/06/action-aims-to-be-the-heroku-of-development-environments-invitation-link-within.php) / [Review by Derrickko](http://blog.derrickko.com/actionio-could-be-a-game-changer) / [Angel List](https://angel.co/action-io) - **[c9.io](http://c9.io)** > [also on GitHub](https://github.com/ajaxorg/cloud9/) - **[koding.com](http://koding.com)** > [on TC](http://techcrunch.com/2012/03/15/koding/) / [Angel List](https://angel.co/koding) I have to admit that i haven't tried one of them yet. I am curious how Git integration will be handled or if Git is no longer needed? I also can't imagine that an online text editor is as fast as something like [Sublime Text 2](http://www.sublimetext.com/2), but let's see. For us, as a PaaS, it is interesting to see how the hosting environment will be integrated. Last click goes to [Brackets](https://github.com/adobe/brackets/) which is also a JavaScript based text editor. But this one runs on the desktop and is open source and from Adobe! # About PaaS pricing Source: https://blog.fortrabbit.com/about-paas-pricing Created: 2015-05-08 Author: Frank Lämmer Tags: opinion > Value-based against cost-based pricing for a hosting service, written when Heroku dropped its free tier and changed the entry plan. ## The Heroku hook Heroku has just [officially announced](https://blog.heroku.com/archives/2015/5/7/new-dyno-types-public-beta) it's [new pricing](https://www.heroku.com/beta-pricing): the free tier is going away, instead there will be a new less expensive entry level plan. What a good opportunity to think about PaaS- and hosting-pricing in general. > Our job is not to host unfinished side projects. **[Quentin Adam](https://www.clever-cloud.com/blog/company/2015/04/14/why-isnt-t-there-a-free-tier-in-clever-cloud/)**, CleverCloud ## Whatever happened to PaaS? This has been asked recently in an [article for TechCrunch](http://techcrunch.com/2015/04/11/whatever-happened-to-paas) by Jon Evan. He claims that Platform as a Service hasn't been the smash hit everyone (Forrester and Gartner analysts) expected. He suspects that the reason is three-pronged: **cost**, lock-in, and culture. ## My two cents Software as a Service offerings mostly have a **value-based** pricing: Pay for the benefit you get out of it. Hosting in contrast mostly has a **cost-based** pricing: Pay for certain computing resources. PaaS is in between: hosting + secret sauce. Most PaaS vendors — including us — don't run the bare metal themselves, they resell hosting infrastructure, the IaaS layer. So the end-user certainly has to pay more (speak double the price) for the secret sauce — the benefit of a managed infrastructure. Can we deliver enough value to justify that? With that in mind, let's see what we can do to convince potential clients: ### PaaS pricing strategies ![Dog fish](/images/paas-pricing-dog-fish.jpg) **Be unlike**: Don't let clients figure out the real resources your are selling. Invent your own units that can't be compared with traditional offerings. PRO TIP: Choose a fancy Japanese naming scheme. That's what the first generation of PaaS was doing. Right now i see a trend towards transparency: most PaaS vendors show actual RAM values these days. Some even differentiate between platform and infrastructure costs. ![Boxes](/images/paas-pricing-boxes.jpg) **Repackage**: PaaS is an abstraction layer on top of IaaS. We don't simply resell EC2 instances, instead our components combine multiple AWS products in a single service, which can be booked small units. ![Speaker](/images/paas-pricing-speaker.jpg) **Pitch the benefits**: "Features tell, benefits sell" they say. Communicate the great value your service delivers. Not everyone is a DevOpPro — it really makes perfect sense to outsource that. ![Deploy now Button](/images/paas-pricing-deploy-now.jpg) **Let users experience the different**: Offer a ~~freemium plan~~ free trial so that users can see the difference themselves. ![Double Claw Hammer](/images/paas-pricing-php-culture.jpg) **Live the culture**: Be closer to your target group by speaking their language and offer custom targeted features. ![Arrow Up](/images/paas-pricing-arrow-up.jpg) **Go bottom up**: Win the heart of your client on a personal level. The developer will make use of your service for his pet project before running his business on it. ### Problems All of the above works for us. However after 3 years of running our PaaS in production the adaption rate feels too slow for me. Beside the usual SaaS seeling hustle I see these two problems unique for PaaS: #### 1: Biased price anchors > What this means for the user: a very linear and predictable pricing model. **[Ben Uretsky](https://soundcloud.com/gigaom-structure/why-you-should-know-about-digital-ocean-if-you-dont-already)**, DigitalOcean Are we in control of our own decisions? Irrational decision making is [everywhere](http://www.ted.com/talks/dan_ariely_asks_are_we_in_control_of_our_own_decisions/) Dan Ariely believes. I think that the DigitalOcean **$5 price tag** is anchored into the minds of our potential clients. So even with all the extra value and all the communication in place, people tend to switch back to simple horse power comparison. It's hard-coded deep into the membrane that hosting is a commodity — check for the specs, check for price, done. With the raise of useful Software as a Service offerings people start seeing actual value in online services. That helps us in the hosting+ area. But it takes time until everyone is ready. One could employ an army of evangelists to change how people think about hosting. Or we simply accept that and try pick up people where they are. #### 2: The developer mindset > Your time as a developer is worth AT LEAST $84/hour. So, if you value your time at all you should stop trying to find a "cheaper" alternative … **[Jeremy Green](http://www.octolabs.com/blogs/octoblog/2015/03/31/analysis-of-the-rumored-heroku-pricing-changes/)**, Octolabs That's true. But we need to respect what makes developers tick: Getting a kick out of solving hard problems and tinkering around. So why not spending plenty hours practicing sysadmin skills to pay a few bucks less for hosting? Again, not a very rational decision, but who cares? ## Bottom line > Price is what you pay. Value is what you get. Warren Buffett Pricing is never isolated, it's always a price-value ratio. GOOD service CHEAP won't be FAST. GOOD service FAST won't be CHEAP. FAST service CHEAP won't be GOOD. For sure our next generation of Apps (working title Hack App) will offer superior technology and we will price it a bit differently. ### Same blog similar topics - **[Cloudscapes revisted](/cloudscapes-revisited-php-cloud-overview)** updated PHP cloud hosting overview - **[Freemium or free trial](/freemium-or-free-trial)** announcement why we skip freemium - **[Perfomance / convenience](/hosting-performance-hosting-convenience)** what matters most in hosting - **[Free web hosting](/free-web-hosting)** ranting about free hosting - **[PaaS vendor lock in buzz](/paas-vendor-locked-in-buzz)** - **[User survey results](/fortrabbit-user-survey-results)** 2013 poll among our users # About writable storage in modern hosting Source: https://blog.fortrabbit.com/about-writable-storage-in-modern-hosting Created: 2012-07-23 Author: Ulrich Kautz Tags: opinion > New-school cloud or legacy LAMP style — what's state of the art in PHP hosting? To understand the issue of writable (or not writable) storage, you must understand the history and development of web hosting technology. Let me begin with … ## A short history of web hosting Web hosting is as old as the (commercial) Internet itself. Once there was the infrastructure allowing you to offer your most important product / ideas / [photos of your cat](http://en.wikipedia.org/wiki/Lolcat) to the whole world, people discovered their overwhelming urge to do just that. However, not many people had the things needed to make their stuff available in the world wide web; so companies were founded to provide the metal and cables for them. Here we were: web hosting providers. On the one hand, gratis hosting services, such as good ol' [tripod.com](http://en.wikipedia.org/wiki/Tripod.com#History), [Angelfire](http://en.wikipedia.org/wiki/Angelfire) (both are now owned by former concurrent Lycos) and [GeoCities](http://en.wikipedia.org/wiki/GeoCities) stepped forward to give away ad sponsored websites for everyone for free. Most of the time with easy-to-use website builders but quite limited in their capabilities. On the other hand, people needed more capable (in terms of available technology and dedicated resources) and above all ad-free services. So paid, shared web hosting providers came to pass and after a very short time, this became a highly competitive market where competitors praised their products in ever more strident voices. Your typical hosting offer of those days read like this: - CGI-bin & PHP incl. - 1,000 GB Traffic - 1,000 MB Storage - unlimited MySQL Databases - 18 ½ mailboxes + unlimited mail forwards - Norton Anti Virus 30 day trial free shipped Of course, those are still around (and most of the websites in the interwebs are probably relying on them). After those (or around the same time) another kind of hosting was born: Do not buy a ready made environment, but the raw resources, setup your environment yourself - the root server. And the derivatives of this, such as vServers, housing your own metal in a provided rack and so on. Each of them (ad-sponsored hosting, shared website hosting, root servers, …) has their own purpose and target audience. However, since those kind of hosting offers were first invented, the Internet constantly grew, new technologies were introduced and previously edge-case-requirements became mainstream. One of them: scalability. The plain website hosting might give you, the developer, a good starting point, as everything is setup for you and you just have to upload your code and are good to go. However, it is most of the time, if not always, quite limited in it's resources. Maybe you upgrade from your M package to L, then XL - but that's about it. Also when upgrading from M to L to get, let's say, an additional MySQL database, your traffic also grows from 5,000 GB to 20,000 GB (or so). Might sound good in the first place, but if you don't need this (and most of the time: you don't), you still have to pay for it. In any case: there is a limited size to which your application can grow and you have to figure out yourself where to go from there. So that is (one possibility) when dedicated root (or managed) servers come into play. You could use the whole resources of the system for your own purposes. But now you have to face other problems: your old environment included probably all kinds of hidden failover measurements (eg your storage might have been in a big redundant storage array of your shared hosting provider). With your own root server, you have basically figure out everything yourself - hello sys-admin. That's where most developers either change careers or outsource those things to people who do this for a living (or just create a free botnet c&c server for everybody to use). In any case, growing above the limits of a single (however large) machine is for most developers (with limited or non sys admin skills) impossible. Sure, there are a lot of companies which can provide the infrastructure and skills - if can afford them. And this is where the new kind of hosting providers stepped in. Since [Google App Engine](https://developers.google.com/appengine/) and innovative hosting providers like [Heroku](http://www.heroku.com) \- everything is rethought and renegotiated. One of the major benefits resulting: you, the developer, can scale resources in real-time to an extend which was impossible beforehand. This new idea of what website hosting is was feasible not only because of new technologies, such as IaaS cloud providers, but also because the website developers became web application developers - real programmers ;). Let me qualify this, before you [smash your monitor](http://www.youtube.com/watch?v=AeDd61n0Kqs) out of anger. When I began programming websites, back in 1999/2000, I wrote CGI scripts in Perl and/or PHP. The developers point of view was kind of page-based. Single sites, which consisted of layout stuff (HTML, CSS, JavaScript) and a bit of logic. Nearly everybody had to be web designer and web developer in one. Nowadays, you have "pure" web developers, aware of far more sophisticated concepts such as [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) and [MOVE](http://cirw.in/blog/time-to-move-on). The website has become a web application with dedicated logic for separated layers. ## With or without writable storage And this is why companies like Heroku can afford to provide a totally different hosting environment which does not even include former corner stones such as writable storage. Now, there is a large number of web programmers which are up for it and do look at this not as an constraint but a possibility - or so it is praised. However, not everything new is good and what works for Ruby or Python developers not necessary work as well for PHP coders. In PHP, you have a huge legacy of established and [widely used](http://techcrunch.com/2011/08/19/wordpress-now-powers-22-percent-of-new-active-websites-in-the-us/) applications. Of course, if you, the PHP developer, start from scratch, writing a completely new app, you could do it probably just as well as the next Ruby guy. ## Why without writable storage anyway? If you are not a hosting provider, you might think: Why not just keep the writable storage? Why drop it in the first place? Well, here is the problem: Those new hosting providers with their fancy scalability need an infrastructure which is scalable to the same degree as their end-user-product! Those infrastructures, eg provided by [Amazon AWS](http://aws.amazon.com/) and [Rackspace Cloud](http://www.rackspace.com/cloud/), come with their own quirks and problems. For example: you cannot predict the IP addresses of your next virtual machine. This one thing right here renders most, if not any, classic failover solutions impossible - or at least so inefficient or fragile that you cannot use them in any production environment. But without them, no hosting provider in their right mind would offer any kind of storage! So we and any other creator of such a modern hosting environment, have to come up with new solutions, which are neither widely documented in the Internet nor tested in millions of hours (hence new). If you cannot or want not expend the effort: no writable storage. ## Contra writable storage Having no writable storage available in the first place forces you to use other storage providers, eg [Amazon S3](http://aws.amazon.com/s3/). A direct result is, that any request to the "static" contents in the storage are not directed to the same machines your app runs on. This not only frees resources on the app server, but is also gives you a good starting situation for putting a [CDN](http://en.wikipedia.org/wiki/Content_delivery_network) on top later on. # Action-oriented UX Source: https://blog.fortrabbit.com/action-oriented-ux Created: 2024-07-24 Author: Frank Lämmer Tags: opinion > Action-oriented UX puts the verb first, closer to how people speak and think, instead of the object-first layouts most dashboards use. ## Object-oriented UX Before explaining my new idea, let's first see how objects and actions usually correlate in UI systems. See this screenshot from the Stripe dashboard: ![Stripe dashboard](/images/stripe-object-ui-annotated.png) I claim: Many user interfaces follow an object-oriented approach. We see lists of objects (items), and by clicking on them, details and possible actions are revealed. This interaction prioritizes the object (the noun) over the action (the verb). This is fine and people are used to it. ## Action-oriented UX Offer an additional verb-oriented entry point: ![Manage landing page](/images/action-ui.png) The screenshot shows available tasks grouped by action. This is an early dummy of our new dashboard (in the making). It juggles multiple object types and serves as the hub for managing collaboration settings. This aims to enhance at-a-glance comprehension of available actions. ### Routes With action oriented UI we can build different kind of routes (endpoints). A user wants to delete an app: - object-oriented: `/apps/ap-1234/delete` - action-oriented: `/delete/app?ap-2134` A user wants to create an app: - object-oriented: `/apps/create` - action-oriented: `/create/app` The action based URLs look better to me, than the object based URLs. They translate better into English language and it least to how I think about systems. ### Relations Editing a relation of two objects can be approached from three sides now. To edit the team-developer relation, a user can start the task in an objected oriented style from the team page by selecting a developer or they can visit the developers page to select a team to proceed. Now with action oriented UX they can also **edit** the relation of these two objects in the first place — start with the action. 'Edit a team developer relation'. This opens a multi-step form. A user selects the developer first, to then edit the roles in teams they are part of. Or the user starts with the team first, then chooses a developer to edit their role. ![Multi-step form](/images/multi-step-relation-forms-annotated.png) Now back to the routes. In action oriented UX the final step can have this pattern: - `/edit/team-developer?tm-324&pe-1234` `tm-123` define the team object and `pe-1234` the person (developer). With these two parameters, this step can also directly linked from the objects. ### CRUD actions only? So far I have explored to apply this pattern for primary actions on objects only. It could potentially also be applied to any kind of additional configurable parameter of objects. A user may want to **change the PHP version** of an environment. With object oriented UX, the user needs to find that setting with the environment. Imagine a search box or command bar where you just type php version to start the process. Next you can an environments from a list. ## We may not ship it To launch a first version of our [new platform](https://new.fortrabbit.com) (hopefully this year) we need to prioritize features. Many good ideas need to be deferred to later releases or even dropped. In this case, the odds are: - It's a lot of work to maintain different entry points to do the same thing. - There are some quirks with flows that don't really fit in the pattern well. - All these options might be confusing. I haven't noticed this concept anywhere else. ## Addendum Of course, only after writing these words, I did a web search on the topic. It seems that Object-oriented UX is indeed a thing, mostly owned by Sophia V. Prater. There is even an acronym: "OOUX" - [www.ooux.com](https://www.ooux.com/) - concepts go much deeper than my lazy sketch above. Yet, my invention now also has an acronym: "AOUX". # Add-Ons markdown Source: https://blog.fortrabbit.com/add-ons-markdown Created: 2014-07-07 Author: Frank Lämmer Tags: chronicles > Price cuts for the Memcache, MySQL and Workers add-on plans, and why cloud pricing has not followed Moore's Law so far. ## Pay less, get more Effective today: We are dropping prices for some of our Add-On plans, including Memcache, MySQL and Workers. No action required from your side — just enjoy the lower costs. A few months ago Google [stated](http://googlecloudplatform.blogspot.de/2014/03/google-cloud-platform-live-blending-iaas-and-paas-moores-law-for-the-cloud.html) that "(cloud computing) pricing hasn't followed [Moore's Law](http://en.wikipedia.org/wiki/Moore's_law) (so far)". In fact exactly that was something I already asked myself. fortrabbit runs on AWS and I was interested on how we should calculate our future costs. It's clear that they will go down, but how much? Not easy. At least, it's good to see that when one big player is moving, the others are following. Now we pass the decreased costs to our clients. We are reducing some of our Add-On plans like this: | Add-On name | Old monthly price | New monthly price | | ---------------------- | ----------------- | ----------------- | | Memcache 256MB | 20 € | 15 € | | Memcache 512MB | 40 € | 30 € | | Memcache 1024MB | 75 € | 60 € | | MySQL dedicated small | 120 € | 100 € | | MySQL dedicated medium | 220 € | 175 € | | MySQL dedicated large | 480 € | 400 € | | Worker micro | 20 € | 17 € | | Worker small | 45 € | 35 € | | Worker medium | 100 € | 80 € | ## MySQL dedicated with more power Beside the price drop, we increased storage for the MySQL dedicated small plan from 10GB to 20GB, to give less CPU intensive applications more room to grow. MySQL dedicated medium and large plans run now on the latest Intel Xeon processor, for faster execution especially on CPU expensive queries. Existing databases will be migrated without interruption. # APM for PHP landscape in 2026 Source: https://blog.fortrabbit.com/apm-for-php Created: 2026-07-13 Author: Frank Lämmer Tags: opinion > A take on PHP application performance monitoring and meta-observability. We are a PHP host. Our customers ship PHP code. When that is slow or blocking, it often ends in a 503 or 504. Then the customer shows up in support, mad about server errors. We recently put together a section on :ContentLink{href="/integrations/apm/intro" text="APM tools" prefix="docs"} in our docs. This post is a snapshot of the scene in early 2026 and our state of thinking. ## Profiler, error tracker, monitor Let's learn the categories: - **Profilers** tell you where time and memory go inside a single request. Think Blackfire, Tideways, PHP SPX, Excimer. - **Error trackers** capture exceptions and stack traces from production. Think Sentry, Flare, Bugsnag. - **APM** sits between them — sampled traces, slow request lists, database query breakdowns, alerting. Think New Relic, Tideways, AppSignal, Datadog. - **Observability platforms** stack APM, logs, traces, errors, sessions, and frontend analytics into one dashboard. Think Datadog, Sentry (these days), PostHog. ## Commercial services Often recommended in the PHP space. ### Tideways Built for PHP, by PHP people, license via `php.ini`, sensible defaults. If you want one tool that profiles, monitors, and tracks errors without sprawling into ten product categories, this is the one we point at most often. No integration yet, but planned. :ContentLink{href="/integrations/apm/tideways" text="Tideways on fortrabbit" prefix="docs"} · [tideways.com](https://tideways.com) ### Flare Error tracking for Laravel, made by the people behind Spatie packages. Narrow focus, very polished. No integration yet, considering it. :ContentLink{href="/integrations/apm/flare" text="Flare on fortrabbit" prefix="docs"} · [flareapp.io](https://flareapp.io) ### Sentry Outgrew "error tracker" years ago. Now it does traces, profiling, and session replay too. The free tier is generous. Multi-stack tracking. No integration planned for now. [sentry.io](https://sentry.io) ### Blackfire The profiler from the Symfony world, nowadays integrated with Upsun. :ContentLink{href="/integrations/apm/blackfire" text="Blackfire on fortrabbit" prefix="docs"} · [blackfire.io](https://blackfire.io) ### New Relic The long-standing enterprise option. Capable and broad, a natural fit for a team that already runs on it. Expensive. :ContentLink{href="/integrations/apm/new-relic" text="New Relic on fortrabbit" prefix="docs"} · [newrelic.com](https://newrelic.com) ### Datadog An observability platform for large, multi-stack setups. :ContentLink{href="/integrations/apm/datadog" text="Datadog on fortrabbit" prefix="docs"} · [datadoghq.com](https://www.datadoghq.com) ## Open source ### PHP SPX A self-contained native profiler with a clean web UI. No agent, no SaaS, only a PHP extension and a browser tab. [github.com/NoiseByNorthwest/php-spx](https://github.com/NoiseByNorthwest/php-spx) ### Excimer A low-overhead sampling profiler from Wikimedia. [github.com/wikimedia/mediawiki-php-excimer](https://github.com/wikimedia/mediawiki-php-excimer) ### SigNoz An OTel-native, self-hostable backend for traces, metrics, and logs. The open-source, self-hosted angle on the same idea as Datadog. :ContentLink{href="/integrations/apm/signoz" text="SigNoz on fortrabbit" prefix="docs"} · [signoz.io](https://signoz.io) ## Privacy Every observability tool ships data off your server. The more tools you wire in, the more places URLs, query parameters, headers, and user IDs end up. Keep that in mind. ## Overhead Modern APM agents should stay under a few percent of CPU. Stacking several of them — APM, error tracker, frontend analytics, session replay — adds up, so it is worth measuring before and after. ## OpenTelemetry [OpenTelemetry](https://opentelemetry.io) is a vendor-neutral standard for traces, metrics, and logs. The promise of OTel is that you can swap your backend without re-instrumenting your code. ## Our take We have always shown basic resource metrics — CPU, memory, request counts. The new dashboard will improve on this considerably (not ready yet), with much better discoverability of issues at platform level. See when an environment is unhealthy, what changed, and where to look first. This will be good for most common use cases, but not replace an APM tool. We can not allow arbitrary code to be installed on the platform. Our architecture is designed to serve web applications, not to run as a multi-app server hosting background daemons next to your code. That shapes which integrations are technically possible at all. We will consider carefully which commercial services to support. Each integration is a long-term commitment: we maintain the glue, document it. We would rather support a small set of integrations well than a long list of half-working ones. --- - [APM integrations](/integrations/apm) - [People problems](/dev/performance/people-problems) # Your responsibility: App security Source: https://blog.fortrabbit.com/app-security Created: 2018-03-28 Author: Oliver Stark Tags: webdev > Ultimately, you are responsible for your code and as well for the 3rd party code you rely on. A few days ago, late in the evening, we received a support ticket with the following message: > My website nicesite.com and the are being redirected to . I haven't changed anything on the site in 2 months. It is not running a CMS and is a simple read-only php app. Have you been hacked? The support team started the conversation with the client and checked the domain routing first. It quickly became clear that the redirects to the phishing domain happened on our platform, so they searched the access logs for suspicious requests. And they found this one: ```plain [11/Mar/2018:00:42:20 +0000] POST "https://www.nicesite.com/root.php?edit=/srv/app/niceapp/htdocs/www/index.php" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" ``` After further communication with the client, the night shift decided to block HTTP requests to this App to prevent redirects to the phishing site. The state of the code base was archived for later. I found the internal team notes and the related support case the next morning. The `root.php?action=path/to/index.php` request smelled like a web shell, a little toolset to manipulate files on the server. **But how did it get there?** Unfortunately, we keep access logs not forever and the malicious code was created 4 weeks earlier. Therefore, the only source I had was the code. Typical culprits for injections are outdated WordPress plugins, unguarded upload forms or sloppy handling of [untrusted data](https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet#Untrusted_data) in general. But I found a little neat application based on `twig`, `league/route`, `michelf/php-markdown`, a few controllers and some markdown files - very similar to our own [help.fortrabbit.com](https://help.fortrabbit.com) site. Everything felt very solid to me. There is nothing wrong with the code, was my first impression. Then I discovered the public GitHub repo of nicesite.com, an exact copy of the hosted site, which included a little demo project in a sub-sub-folder. And this project included a `vendor` folder with a few dependencies, namely `symfony/http-foundation` and `phpunit/phpunit`. **Long story short**, an unpatched phpunit (CVE-2017-9841), accessible via HTTP, as the vendor folder lived inside the document root, was most likely the entry point for the hacker. I came back to the developer with my investigations. He patched his code immediately and replied as follows: > THANK YOU. I will definitely be recommending your service from now on. The other PaaS providers haven't been nearly as helpful. ## Takeaways Ultimately, you are responsible for *your code* and as well as the 3rd party code you rely on. There is a ton of information about Web Application Security on [owasp.org](https://www.owasp.org), on [websec.io](https://websec.io/) Chris Cornutt covers the PHP world and here are the three takeaways I can provide from this particular case: ## Keep your dependencies up-to-date Sensio Labs provides a [security checker](https://security.sensiolabs.org) that allows you check your dependencies for known security vulnerabilities, via API, command line tool or web interface. The database does not include all composer packages, but the most common ones. Download the .phar and make it globally executable to integrate this task in your workflow: ```shell curl -O http://get.sensiolabs.org/security-checker.phar && \ chmod +x security-checker.phar && \ mv security-checker.phar /usr/local/bin/check ``` With this bash one-liner you can `check` all your projects at once from the parent directory: ```bash for project in */; do check security:check "$project"composer.lock; done ``` ## Prevent direct access to the /vendor folder The following directory structure is very common when you use a framework like Symfony or Laravel: ```plain . └── htdocs ├── composer.json ├── composer.lock ├── vendor └── public << Your document root (www or web is common as well) ``` As there is no need to access any PHP library directly, you should prevent it. By following the structure above, a `index.php` is the only PHP file in the document root. The actual project code and the composer dependencies are not accessible. If your project dictates a different structure, with the `vendor` folder under the document root, prevent access - via .htaccess like so: ```xml Allow from None Order allow,deny ``` ## Be aware that public repos are visible to everybody Don't get me wrong, open source is great! But think twice before publishing something on github or other public repositories. Crawlers, bots and even humans will find it. Not everybody has a white hat mentality and will let you know about possible issues. Really important: Never store sensitive information like passwords or access tokens in git. Remember, git never forgets! If you have committed sensitive information by accident, even if you revert the mistake, it will stay in the git history. # Autoscaling now available Source: https://blog.fortrabbit.com/autoscaling-now-available Created: 2026-03-25 Author: Frank Lämmer Tags: changelog > Autoscaling arrives for MySQL, web storage and traffic: plans move up when usage grows and back down again, without any interaction. ![Autoscaling in action](/images/autoscaling-video.gif) What it looks like. Just a little checkbox. ## What autoscales, what doesn't | Component | Autoscaling | Metric | | ----------- | ----------- | ---------- | | MySQL | Yes | Storage | | Web storage | Yes | Disk space | | Traffic | Yes | Bandwidth | | PHP | No | — | | Jobs | No | — | | Backups | No | — | ## Autoscaling ON vs OFF | Autoscaling | Fixed pricing | May go offline if exceeded | | ----------- | ------------- | -------------------------- | | On | No | No | | Off | Yes | Yes | - Autoscaling is optional. You can turn it on and off at any time. - See :ContentLink{text="autoscaling docs" href="/platform/billing/autoscaling" prefix="docs"} for more details. ## Getting started with autoscaling :BlockLink{title="Edit components for {{app-name}} / {{app-env-name}}" path="/environments/{{app-env-id}}/components"} New apps created from now on have autoscaling preselected. Existing environments created during the public BETA so far have autoscaling off (to not create surprises). To enable or disable autoscaling for an existing app environment: 1. Go to our :ContentLink{text="dashboard" href="/" prefix="dash"} 2. Navigate to your environment's components 3. Toggle autoscaling on or off 4. Choose a starting tier (XS keeps baseline costs low) ## Pricing considerations With autoscaling enabled, monthly invoices may fluctuate. This is usually minimal thanks to :ContentLink{text="tiered pricing" href="/platform/billing/tiers" prefix="docs"}. Unlike per-MiB billing, tiers are designed so plan changes happen rarely. Monitoring and pro-rated costs are visible in the dashboard. - **Minimize costs**: Start on XS plans with autoscaling on. The lowest possible base that scales only when needed. - **Minimize price fluctuation**: Book a larger base plan. Tiered pricing means most months you won't move a tier anyway. - **Hard budget cap**: Disable autoscaling. Get email warnings before hitting limits. ## Notifications We are also intoducing a first iteration of metric notification with this release. With autoscaling disabled, the system will send an email to all technical contacts of the app about the approaching limit. To avoid sending too many emails, this email is only sent once a month per environment. It will be sent the first time you're close to the limit. ## How we got there This release was a big technical challenge. Changing resources without interruptions in an environment that has persistent storage isn't exactlty easy. Some thinking outside the box and a lot of communication was required to get it right. But we are happy with the result. It's an important milestone for future updates. ## Outlook Today, autoscaling is limited to usage-based components with clear signals for when to scale. For compute performance components such as PHP and jobs, autoscaling is more complex and specific per project. It needs careful thresholds and notification settings. Follow this blog for future updates. We have a [dedicated RSS for posts tagged as changelog](/feeds/tag/changelog). ## Other updates - New pricing details page: [fortrabbit.com/pricing/details](https://www.fortrabbit.com/pricing/details) - More payment types: SEPA direct debit, Google Pay, Apple Pay, Klarna … - Fixed issues when installing LightningCSS and Bun (during deployment) - Added an early :ContentLink{text="Tempest install guide" href="/guides/more/tempest" prefix="docs"} - PHP processes got a small bump - Many minor improvements and bug fixes --- - [About autoscaling](/platform/billing/autoscaling) # Battling with billing Source: https://blog.fortrabbit.com/battling-billing Created: 2015-03-24 Author: Frank Lämmer Tags: opinion > How hustling with accounting keeps us away from developing our service. We are developers without much backgrounds in accounting and bookkeeping. Still we need to bill our clients for our hosting service here. We have learned some lessons the hard way and I still find it surprisingly difficult. We have put huge efforts in optimizing these processes. Time we would rather have spent developing the platform itself. ## 9 billing mistakes to avoid Maybe the following list helps you to avoid some mistakes upfront: ### 1: Avoid a complex pricing model ![Complex pricing](/images/complex-pricing.jpg) By any chance: Just run a SaaS with three simple plans to subscribe to. That makes everything simple. We instead have a complicated product structure. It's quite fair for clients, but makes everything fairly complicated for us. ### 2: Don't do B2B and B2C ![B2B and B2C](/images/b2b-b2c.jpg) Do your business with end consumers, it's easy. Business to business is more complicated. Don't do both, like we do. Our service is mostly booked in B2B scenarios. But especially during trial and boarding people just wanna use it. That's personal. Also freelancers and small business are sometimes not that professional. How do you communicate your prices — with or without VAT? What about legal issues? What about consumer protection? Do you want to reject customers from booking when they don't have their VAT IN handy? ### 3: Avoid consumption based billing ![Consumption Billing](/images/consumption-billing.jpg) A cloud hosting service is expected to be on demand, pay only for consumed resources. In our case the minimum billing period is one day. So we'll invoice at the end of the month and collect the money a few days after. This is not only bad for the cash flow it is specially hard to communicate. People expect to be charged right after they clicked the "book now" button. We get lot's of: "Why i am still charged for this App?" support tickets. But hey, it's the only way to do this. Your telephone bill most likely also work like this. ### 4: Don't do everything by yourself ![SaaS billing software](/images/saas-software.jpg) You have not done any of the mistakes above so far? Great you'll hopefully find some online service to help with your recurring billing. Send some data to their API and you are done. But for us, only enterprise billing solutions seem to fit our requirements. Those are mighty but really hard to handle, old-school and expensive. We have used Freshbooks in the beginning, but that was even a bigger mistake as the service is mostly meant for personal use, not batch invoicing. Now we generate and send invoices on ourselves. ### 5: Don't rely on a foreign currency ![EURO currency drop](/images/currency-drop.jpg) When we started our business the EUR to USD exchange rate was about: **1** to **1.30**. Now we nearly see parity between the two currencies. Our biggest monthly spending is for AWS, which we have to pay in USD. So as you might can imagine, we are paying much more for computing resources now. In our financial forecast models we have estimated conservatively with an exchange rate of **1.20**. This now is just terrible. It pulls us down. We had to cut nearly all marketing spendings. ### 6: Avoid to do business in Europe Our US SaaS business partners are sending us monthly payment receipts like this: "You are awesome. We have just charged you a XXX. Thank you for business!". This, of course, doesn't meet any accounting requirements here in Germany, EU. And it shows me how easy it is to do business in the US. #### New tax laws hustle The EU's new VAT laws are a mess for B2C businesses who are delivering electronic goods. VAT is not charged on the seller's country anymore, it now will be collected on the customer's location. Sure, that's easier for the end user. Now we need to keep a database of EU countries with according VAT rates and declare VAT for each country individually — on a monthly basis. MOSS (Mini One Stop Shop) is a system meant to simplify that. Here you can declare all the different taxes at once. The only problem: It's not documented at all and there is no API to send the data over. So we are preparing our data accordingly in extra CSV files and hand it to the tax consultant who then uses some proprietary software to declare the MOSS. By the way: Did you know that the A2 country for Greece is GR, but the two digit tax code is EL? #### Don't forget to validate your clients VAT IN ![Validate VAT IN](/images/vat-in.jpg) For B2B business inside Europe across country borders no VAT is required at all. This of course only applies when you note the clients VAT Identification Number on the invoice. So your clients need to enter their VAT IN. Then you need to verify if there is really a business associated with the VAT IN entered. There are VIES servers you can ask. Sometimes the VIES servers are just down, that means no business for you. At the beginning we didn't validated VAT INs entered by our clients. Half a year after we started the business, we got a letter from the »Bundeszentralamt für Steuern« with all the wrong VAT INs. Ouch: We payed the 19% VAT for most of those invoices. ### 7: Don't try to change your payment provider ![Payment provider](/images/payment-provider.jpg) Your credit card payment processing provider (credit card clearing) will lock you in. At the time we have started, Stripe was not available in Europe. So we settled with WireCard. Stripe is here now and we considered to switch. But — being PCI compliant — you don't store your clients credit card credentials yourself. So switching payment gateway means that your clients need to re-enter their credit card credentials. No way. ### 8: Don't offer multiple payment methods ![Payment methods](/images/payment-methods.jpg) Besides credit card we also offer SEPA payments. We have a cool semi-automated workflow here where we work directly with the bank — read less payment processing fees. But: you don't get immediate feedback if the payment succeeded. A lot of manual checks! ### 9: Hire the right tax pro ![Tax pro](/images/tax-pro.jpg) Tax professional are living in a parallel universe from us. I asked many people and called quite a few tax offices. Most weren't even interested in a young company at all. Others are expecting you to send over all receipts printed on paper. Finally we started fresh with a young team. Nice: they accepted a bunch of PDFs in a shared cloud folder each month. But the spirit of optimism turned into horror for both sides. While I imagined some smart software to parse all the documents, they booked receivables one by one. At the beginning that doesn't mattered much. But later with a few hundred outgoing invoices each month this turned into a waste of human resources. We could improve that by providing extra CSV files to include all data. But how could we possibly find out which invoice was paid when? For SEPA direct debit we can see a bank transaction for each invoice. But the payment provider collects all the payments, subtracts his fees and then transfers one lump sum to our bank account. Impossible to see which invoices have actually been paid. We figured it out, but it wasn't easy. Our tax office surely had a hard time with us. I am glad they stayed with us. --- > Let me tell you how it will be > There's one for you, nineteen for me > Cause I'm the taxman, yeah, I'm the taxman The Beatles --- Disclaimer: This post isn't meant as any legal or financial advice. Contact your accountant for specific tax advice. # BETA begins Source: https://blog.fortrabbit.com/beta-begins Created: 2012-08-30 Author: Frank Lämmer Tags: chronicles > The private beta of the fortrabbit PHP platform opens and the first invitations go out. What testers can expect during the beta period. We are happy to announce that we have finally started the private BETA of our upcoming PHP Platform. The first invitations are sent out. Thank you for your interest and for waiting so long.\*\* ### Informations for BETA Testers During the BETA period all services are free. Even when prices are shown, nothing will be charged. Accounting is one of the things that needs to be tested. The BETA period is not going to be very long. We think it will be only a few months. Expect some hiccups! We are already running some live websites on it, but not suggest that you should to do so as well. We still do load tests, DOS attacks and other stuff to stress the system. Please share your thoughts with us! It is extremely important for us, what you think about the service. Do you understand everything? Where do you have problems? What are you missing? ### Don't miss the launch Please subscribe to our [RSS](/feed), follow us on [Twitter](https://twitter.com/fortrabbit) or leave your mail address [here](http://fortrabbit.com/) to get notified when our platform will be available for everyone. ### What you can expect from us The platform is exclusively made for PHP developers. You don't need to master a Ruby based Command Line Interface, there is a simple to use web GUI. No fancy one-click installers but powerful tools to manage your code. ### Want to join the BETA? You have missed the early bird sign up for BETA period? No problem, just [write us an e-mail](mailto:info@fortrabbit.com?subject=Gimme%20BETA). # BETA survey results Source: https://blog.fortrabbit.com/beta-survey-results Created: 2012-08-23 Author: Frank Lämmer Tags: opinion > What 160 developers told us about their PHP workflows, hosting and tools, and how the answers shaped the platform we then built. We have asked our readers a few questions on their PHP workflows, hosting and tools. We are very curious about this, because we want to build the best PHP PaaS for dev guys. Here are some of our learnings: - About 160 people finished the survey (cool!) - Zend is the most popular Framework - More people deploy code with Git than with FTP - Memcache is the most popular caching engine - MySQL is still THE database of choice, followed by MongoDB - Most coders want SSH access - A fully managed platform is more important than full root access - A multistage deployment (testing, staging, live) is preferred - Reliability, performance and price are core factors for hosting Thanks everyone for taking the time. We have already implemented some new features based on this feedback. The survey was a fun ride, we have currently set up another more general one here: [coders-survey.com](http://coders-survey.com). And yes: We are rolling out the private BETA soon. [Download Survey Results printable PDF](/images/fortrtabbit-beta-survey-results.pdf) ## Written answers, grouped and ordered by importance ### What other software requirements you have? - PHP >= v5.4 - mod_rewrite is a must - Caching (APC/Memache/Redis) - Direct file-system access via SFTP/SSH - SSL, file storage, gd and cron task - Version Control (git/svn) - Composer/packagist integration ### "Must have" SSH commands/tasks: - Basic file manipulation (find, cp, mv, mkdir, tar, zip) - Log access (tail -s php_error.log) - Misc (cron, vim, wget) ### Describe your preferred Backup strategy - rsync over ssh - scheduled backup to Amazon S3 - tar.gz and download via ftp after - daily and on-demand exports of db's and application files to a server off-site # Introducing a better domain handling Source: https://blog.fortrabbit.com/better-domain-handling Created: 2016-07-12 Author: Frank Lämmer Tags: changelog > Domain setup on fortrabbit gets a clearer interface and a forwarding service for naked domains, following free HTTPS via Let's Encrypt. Just last month we have launched [free https](/tls-free-launched) (via Let's Encrypt) for all custom domains. Now we are continuing in this direction with a new forwarding service and more descriptive domain setup and management. ## Naked domain forwarding TLDR; We will now provide A-records for your naked domains; here we forward requests to www. ### A little refresher - `blog.fortrabbit.com` and `www.fortrabbit.com` are subdomains - `fortrabbit.com` and `fortrabbit.co.uk` are naked domains, aka Apex domains In classical hosting you usually use A-records to route your domain to the IP of your web server. In modern hosting you use CNAME-records to route your domain to your App. ### Naked domains — until now In general you should route your domain using a CNAME like so: ``` NAME TYPE VALUE ---------------------------------------- www.mydomain.com. CNAME myapp.frb.io. ``` This keeps your App movable: the IP behind `myapp.frb.io` can change without your knowledge, due to re-balancing, scaling, maintenance and other scenarios. But until now it was not clear how naked domain should be handled. ### Bad practice until now - don't do this 💣 **Simply using the CNAME for naked domains**. That is against the [DNS specs](http://www.ietf.org/rfc/rfc1035.txt) and it breaks emails for `you@domain.com` — CNAME on a naked domain breaks the MX record so you and cannot receive emails on that domain anymore. **Ignoring naked domains**. That is not good, as some users might try to enter the domain without the . prefix in the browser which would end up in a dead end. **Using the IP address of the App for the A-Record**. That's not good, as your App might be moved around and thus will receive a different IP. **Using naked and www side by side, not forwarding requests**. This way the Google bot and your users don't which domain is the right one. ### Hacks until now ⚡ Until now, we recommended to rely on third party services to remedy this problem. There are specialized DNS providers, offering so called ANAME or ALIAS records, which circumvented the problem using a trick - or services like [WWWizer](http://wwwizer.com/), which offer a free redirect service for naked domains. ### Naked domain forwarding from now on ✨ From now on, we offer **free forwarding** for domains used with your App. Also we have combined this new service with our Let's Encrypt update, so redirecting always serves a valid and free certificate. Using the above example, you can now setup your records like so: ``` NAME TYPE VALUE ---------------------------------------- mydomain.com. A 52.18.136.112 www.mydomain.com. CNAME myapp.frb.io. ``` For EU clients it's the IP: `52.18.136.112`, for US clients it's: `50.16.35.210`. You can point any naked domain to the above IPs and they will be redirected automatically to the corresponding `www.` subdomain. Just make sure you have added the `www.domain.tld` to your App before, and it's a "New App". ### Why this matters Most of our clients are using classical domain providers for domain registration. Those services often don't offer forwarding. In consequence, clients needed to make use of a third party service and dirty hacks. ### Best practices — do this 💚 - Use CNAMEs for routing - Forward all requests on the naked domain to the www domain - Enforce HTTPS by redirecting non HTTPS requests to HTTPS - Use [HSTS](https://help.fortrabbit.com/tls#toc-force-https-for-future-visits-with-hsts) to force HTTPS within the browser ### Alternatives The new domain forwarding feature is optional. You can also use any other service in combination with fortrabbit. There are specialized DNS services — like [DNSimple](https://dnsimple.com) or [DNS Made Easy](https://www.dnsmadeeasy.com) — offerings the aforementioned ANAME or ALIAS records, enabling CNAME-like behavior with a naked domain. [Cloudflare](https://www.cloudflare.com/) does all kinds of magic with your domain which allows you to use naked domains with fortrabbit. ## Dashboard improvements Apart from this nice new forwarding feature, we have also tweaked the processes of setting up and managing domains in the Dashboard. It's now more intuitive when getting started and more descriptive when looking for troubleshooting. You can compare the current (actual) DNS settings of your domain with the supposed (target) DNS settings. We can show you, if a domain is routed correctly or if something is missing. Wildcard handling was also improved. Additionally, you now get infos on the TLS status and if your domain is available over HTTPS. ## Wrap up Now: Isn't fortrabbit your best PHP hosting platform ever? All domains with fortrabbit Apps get zero-config HTTPS via Let's Encrypt and to all "www." domains, there is an automatic forward from the naked domain. ## Further readings We have also updated our [help page on domains](https://help.fortrabbit.com/about-domains). # Billing provider research Source: https://blog.fortrabbit.com/billing-research Created: 2025-01-09 21:31:03 Author: Frank Lämmer Tags: chronicles > Choosing a billing provider for a hosting platform: the requirements, the candidates, and why a homebrew system finally had to go. ## Motivation We are currently building a [new platform](https://new.fortrabbit.com) version for our PHP hosting service. For the current platform, we have a custom homebrew solution, which serves us surprisingly well for a decade already. Yet it shows signs of age and is missing some features, PDF invoices for example. For the new platform, we aim to slim our codebase to launch sooner and reduce technical debt. Ideally, the billing service should be future-proof, minimizing the need to adapt to changing accounting requirements. For instance, updating VAT rates in the European Union automatically. When we first started, invoice and billing solutions for SaaS businesses were just emerging and lacked essential features. Stripe was not yet available in the European market. We initially used WireCard, but that's a different story. ## Our complicated requirements We designed our new product catalog without constrains. It's conceptually similar to our current platform. - Invoice at end of month, for backdating service period - Prorated after usage per day - Plans grouped by component - Clients can book multiple apps ### Product structure ```md - PHP - XS - data center US1 - price EUR - price USD - data center US2 - price EUR - price USD - data center EU1 - price EUR - price USD - data center EU2 - price EUR - price USD - SM - … - MS - … ``` Above, an excerpt of the product structure. PHP is the product. XS is the first size (plan). It has different prices in different data centers and of course also in different currencies. ```md - My super app -> group (project) - production -> sub group (environment) - PHP XS - Storage XS - MySQL SM - development - PHP XS - Storage XS - MySQL SM - My other app - production - PHP XL - Storage MD - MySQL SM - Jobs XL ``` Customers book apps (projects by their own name). Apps can have multiple environments (versions). Components are booked per environment. Each component is booked with one plan (size). ### Invoice structure ```md | Item | Daily price | Days used | Price | | ---------------- | ----------: | --------: | -----: | | My super app | | | | | production | | | | | PHP XL | 3.00 | 30 | 90.00 | | MySQL XS | 0.30 | 30 | 9.00 | | Traffic XS | 0.30 | 30 | 9.00 | | Storage XS | 0.30 | 30 | 9.00 | | development | | | | | PHP XS | 0.30 | 15 | 4.50 | | MySQL XS | 0.30 | 15 | 4.50 | | Traffic XS | 0.30 | 15 | 4.50 | | Storage XS | 0.30 | 15 | 4.50 | | ---------------- | ----------: | --------: | -----: | | My other app | | | | | production | | | | | PHP XL | 3.00 | 30 | 90.00 | | MySQL XS | 0.30 | 30 | 9.00 | | Traffic XS | 0.30 | 30 | 9.00 | | Storage XS | 0.30 | 30 | 9.00 | | Redis XS | 0.30 | 30 | 9.00 | | Backups XS | 0.30 | 30 | 9.00 | | ---------------- | ----------: | --------: | -----: | | total net | | | 300.00 | | VAT 20% | | | 60.00 | | total gross | | | 360.00 | ``` At best, the customers get an invoice as outlined above to understand how costs where aggregated over the backdating period. In this example the development environment was booked for half the month. ## Billing service as a hub My understanding of a billing service is that our application will send booking and usage data to the billing service, which will then handle all other aspects of billing. It includes financial business intelligence, covers compliance and tax-related topics, and offers standardized interfaces to connect to third-party services. Invoices and receipts are created and sent automatically. Additionally, collection, retry, and service cancellation (on bounce) are automated. You can likely find an accountant already familiar with the system. The billing service will return a list of products with cost to populate the pricing page. It also provides information on what the customer can expect for their upcoming invoice. The billing service is smart so your application does not need to be. ## A confusing market Armed with my list of demands, I set out to find a suitable solution. I explored websites, read documentation, created accounts, and browsed product demos. However, there wasn't enough time for thorough testing and in-depth analysis of each service's pros and cons. I had to resort on gut feeling and quick decision-making based on vague assumptions. The following list of SaaS billing service providers is sorted in the order I approached them, giving you an idea of the time and effort invested. ### Costs I will not highlight price differences. Partly because it's hard to estimate final costs, partly because our main goal is to ship quickly and to have a good and stable service. Billing can be costly. Open source community solutions can offer the best price: zero. ### Stripe Billing We use Stripe as a payment processor already. I am following their development and appreciate their developer focused approach. It's obvious, that they dominate the market. I attempted to schedule a sales call to discuss my requirements, but it wasn't possible within reasonable time. Perhaps I was too impatient or didn't phrase my questions clearly enough. 🚩 It seems that our product structure cannot be mapped effectively with Stripe Billing. However, Stripe Invoicing, which is more flexible, might fit. Stripe has developed sophisticated methods to make their service appear complex, making it seem challenging to build and maintain your own solution. When using Stripe Billing, you must use Stripe as your payment processor. Other billing services often offer more options and even support multiple payment providers simultaneously. - Dashboard is fancy, yet solid - Docs, test mode and time simulator are nice - [stripe.com/billing](https://stripe.com/billing) ### Lago The first open source solution with community edition and paid service I discovered. I had a sales call with Raffi to discuss my requirements and learn about the costs and differences between the paid version and the community edition. Unfortunately, we are too small for their cloud solution. Top companies using Lago have multi-million dollar valuations or are at the Series A stage - Laravel is listed among them. The video call was very short. So I installed the Docker container of the community edition and clicked around, created some products and customers. It has certain features, that are missing with Stripe. Quite a few features (too many?) are disabled with the community edition. My local setup was broken, after I installed an update. - Open source, community edition = light version - Periodically featured on Hacker News - Not on par (yet) with Stripe and other commercial solutions? - Active development - [getlago.com](https://www.getlago.com/) ### Chargebee - Comprehensive interface, impressive details for settings - Things are where I expect them to find! - Integrations we can not afford: Anrok, Vertex, Taxamo - Tax setup and configuration looks promising - Nice: reminder to update payment method - Day-based pro-ration - Product families to group PHP xs - xl - Tax configuration looks promising - (New) RevenueStory looks super too - [Some bad reviews at Reddit](https://www.reddit.com/r/SaaS/comments/t250a9/stripe_subscription_vs_chargebee_what_to_choose/) - [chargebee.com](https://www.chargebee.com/) - from India ### Kill Bill - Open source around for a longer time - Nicely written docs - Interface is very bare bone - No PDF support out of the box - [killbill.io](https://killbill.io/) ### Recurly - Hm. A lot of B2B, 'By industry', 'blurry logo' - Calendar billing (maybe matching our model?) - [recurly.com](https://recurly.com/) ### Paddle - New sexy (stripe-like) version, maybe too shiny? - To prorate and bill on the next billing date. - Looks a bit basic compared to Stripe / Chargebee (no-code, low code) - 'Merchant of record' (MoR) = legal entity for selling goods on your behalf - from London, UK - [paddle.com](https://www.paddle.com/) ### Maxio - formerly SaaSOptics and Chargify - [maxio.com](https://www.maxio.com) ### Lemon Squeezy - [lemonsqueezy.com](https://www.lemonsqueezy.com/) ### Billabear During my research I was looking for an article like the one you are reading now. Unfortunately, search results are all crowded with advertising driven comparison websites. But on [Reddit r/php I discovered Billabear](https://www.reddit.com/r/PHP/comments/1e9angm/billabear_a_symfony_powered_subscription/). I had a call with founder Iain. He is working on this for three years and knows his domain very well. The service offers a comprehensive feature set. The pricing scheme seems to perfectly fit businesses of our size. I am digging his build in public approach, [discussions on GitHub](https://github.com/billabear/billabear/discussions). - It's build with Symfony - Made in Berlin 🐻 - Invoice templates in TWIG! - Still early stage - [Billabear](https://billabear.com/) ## Thoughts I like the idea of using a billing service hub. Yet. Our product structure and business model, as it currently looks like will not match with any of the services well enough. During the process, I even considered radically redesigning our product structure to align with the billing service. Offering three simple plans paid in advance (perhaps annually) could lower the entry barrier compared to our current 8 components available in multiple sizes. However, I believe our product structure fits real-world requirements well. Websites have different requirements, and our detailed offering allows customers to book only what they need. "A different kind of hosting" is our motto, after all. We naturally have responsibilities on our side. fortrabbit is not a SaaS, but a PaaS, there is a infrastructure platform attached. For instance, before we can send events to aggregate usage-based (metered) plans, we need to have a clear understanding of the usage ourselves. We need to accurately track and display web storage usage and traffic in relation to the booked plan. When autoscaling is disabled, capping needs to be applied or new resources need to be provided. I have the tendency to default to the biggest provider, we do so for [our infrastructure](/infra-research-2024) already. What if the small service provider goes out of business or pivots to a different business model? Yet, I expect from our own clients to find trust in us, a small service as well. I am a visual person. The interface UI sells to me! If a dashboard is not designed well, I immediately loose trust and confidence. Even small details like a blurry pixel logo, a typo or inconsistent wordings immediately raise red flags. In addition, any enterprise sales talk will immediately turn me off. Leave me alone with your case studies, your solutions by industries. Show me the API documentation. We address a global market. Yet we need to comply with local tax rules in Germany and Europe. Most providers seem to be ready for that. Yet having something more local is appreciated. E-invoicing does not seem to be a hot topic yet. ## Current state We haven't made a final decision yet. It will take a while until we approach technical implementation. We tend towards using Stripe Invoicing, but not Stripe Billing. By only using Stripe Invoicing we get more freedom to structure the invoices in our desired ways, grouping products by apps. It seems to be the right abstraction for us, right now. We keep the central logic, but there is a service to outsource the invoice creation. But I will also continue to explore alternatives and the red flag with sales will not be forgotten. I learned a lot about decision making and product discovery. ## What's in it for you Making a buying decision is hard, cause it's a market of lemons. You will probably have to resort to recommendation or some peer signal you received. Sorry that I can not present you a winner here. Keep an eye on data ownership and lock-in. Fun fact: I almost forgot, we used to run an invoice service for small businesses/freelancers too, anno 2012, [Waybackmachine](https://web.archive.org/web/20120706000542/http://webrechnung.info/). # Blackfire profiler on fortrabbit Source: https://blog.fortrabbit.com/blackfire-profiler-on-fortrabbit Created: 2015-01-21 Author: Oliver Stark Tags: changelog > The Blackfire PHP profiler becomes available on fortrabbit, and how a sales pitch from SensioLabs turned into an actual integration. tldr; We are excited to announce the availability of the Blackfire profiler on fortrabbit. ## Prologue We get a lot of sales pitches, recruitment offerings and partnership requests. We usually kindly ignore all of it. So we did with an email from Olivier Creiche — actually his company SensioLabs should have ringed a bell. Anyways, he gave us a call and we quickly arranged a skype call with Fabien Potencier who himself! gave us a demo of the new Blackfire profiler. With technical guidance form Nicolas Grekas we tested the Blackfire setup in our test environment and finally soft-launched it last friday in production. ## Why profiling anyways? Today's web applications can quickly become complex under the hood. Thanks to Composer we can rely on existing packages without reinventing the wheel. Especially frameworks, CMS and e-commerce systems give you a lot of boilerplate and convenience for your development process. But this also means you hardly can understand every single bit of code you are using. Web applications are usually fast after the launch, but degrade over time. They receive more requests and process more data. You add more features and at some point everything or some parts of your app become slow. But where to start investigating — guessing and trial and error? Profilers to the rescue! They give you deep insights of your code and all dependencies that are involved to handle requests. ## Blackfire vs. other profiling tools ![offload.io screenshot](/images/blackfire-gui.png) The XDEBUG profiler and XHPROF are around for a while and known in the PHP world and are the defacto open source standard. They collect a bunch of data for every single function call in the request-to-response lifecycle. Tools like KCacheGrind, MacCallGrind, Webgrind for XDEBUG and xhgui, uprofiler for XHPROF help to analyse and visualize this data. If you ever tried one of these you know that all these metrics, such as wall (elapsed) time, CPU time and memory usage, can be overwhelming. My first impression of Blackfire was a similar one, a call graph, tables with data. But it took me not long to get into it and understand the differences. The GUI is actually pretty neat and helps you to distinguish relevant from irrelevant data. You can create multiple slots to store your results and you can even compare two slots, before and after your optimization for example. Last not least: the setup takes less than 5 minutes — then you can start profiling. And you can profile applications in production as well! I am convinced. # That bounced payment Source: https://blog.fortrabbit.com/bounced-payment Created: 2016-01-28 Author: Frank Lämmer Tags: chronicles > One complicated support ticket about a bounced payment, printed almost in full — on privacy over convenience and disaster communication. Filed under: daily operations, book-keeping, best practices in worst scenarios, privacy over convenience, disaster communication, company culture, late paying customer, drama … Disclaimer: Mails slightly edited. ## The conversation ### Client Hi fortrabbit support, I have just paid. Now it would be really nice if you could restore my App. ### My answer Hi client, sorry, no good news for you: I finally could get hold of a technician. I got confirmed that it is not possible to recover deleted Apps. I can totally understand your frustration at this point. You have just paid all open invoices in good hope to get your data back — and now we don't help you out here. As much as I would like to help you here, I can't. Deleting data is required as we don't want to store any more informations from our clients than we have to (we already need to store billing informations for 10 years!). When a client decides to leave or delete something, it should be really gone and not just don't shown up any more. So this is actually a good thing in terms of privacy. Deleting an App is final. It's also not our intention to hostage your data in such a way: "Pay us to get your data back". We have friendly practices regarding bounced payments. Other providers will immediately kick you out when a payment has bounced and you have not reacted within a very short time frame. We wait for at least two invoices were bounced permanently. We'll immediately send a warning mail when a payment does not succeed. We also retry periodically charging the card again. There is also a big yellow warning about open invoices, whenever you log in to the Dashboard. You can initiate a payment any time yourself and you can change the type of payment as well. In your case, already 4 invoices were bounced, I think. During the first weeks of the month we manually check for clients with multiple outstanding invoices and kill associated Apps to avoid further costs on both sides. Sorry again. ### Reaction The client didn't went berserk after all this. My highest respect for this! ## My thoughts Getting paid is difficult, as well as not getting paid. Dealing with bounced payments costs us time and money. We have to pay for each failed credit card transaction — in some cases more than the sum of the actual invoice. We are allowed to pass those costs to the client, but we don't do so (yet). By now, in the third year of our business we have collected quite a sum of open invoices. We could commission a debt collection agency or a law firm to represent and ensure our interests, but that's really not our style. I guess that's just the way this all works and there is no easy way around it. Let's keep calm and code on. ## Further readings - [Battling with billing](http://blog.fortrabbit.com/battling-billing) my list of obvious billing mistakes for founders # Building websites in the age of AI Source: https://blog.fortrabbit.com/building-websites-in-the-age-of-ai Created: 2025-07-22 22:03:31 Author: Frank Lämmer Tags: opinion > AI site builders generate code, content and layout in seconds. What that leaves for the people who build websites for a living. > Computers are like a bicycle for our minds. > -Steve Jobs AI based site builders can generate code, content and design layouts in seconds. Everybody can ask an AI to 'make me a website for my bakery' to get a decent looking result. The barrier for launching a website has never been lower. AI-generated sites are just 'good enough' for many scenarios. > Today, any fool can use a computer. Many do. > -Ted Nelson ## Creation of websites It's die or adapt for the classical web developer working for clients directly. Your job is at risk. Shift competences if you want to keep your skills a profession and not an esoteric hobby. I'd say: Embrace and level up. Invest in strategy and user experience, where human creativity, taste, and empathy still matter. Pursue higher-value, custom design, complex integrations, unique experiences. ## Consumption of websites Humans may not look at the website you are building right now, but for sure some AI bot will happily scrape it. AI will eat the web we know for breakfast. People will consult AI instead of the old fashioned searching and surfing. Plummeting activity on StackOverflow is just one visible sign for this. But hey, the web today is already broken. Search engines are increasingly unusable. Content is stretched to maximize ad impressions, designed to benefit business interests. I often find myself searching on Reddit when looking for an opinion. Meanwhile AI will flood the web with more homogene websites, further diluting content quality and destroying trust. The idea of the web as a vast, open sea of free quality information has been fading for years. There are still unique websites, but finding them get's harder and harder. As AI will become more commercialized and VC funding dries up, it too may become just bloated. Just think about YouTube in the early days and now. AI is in the early fun days now. Enjoy. ## Vinyl diggers I'd like to keep my quirky web. About 30 years ago I was looking amused at my dj friends. They were still buying vinyls instead of CDs. Fast forward to now. The CDs are long gone. But you can still play vinyls from the 1960s. New vinyls are still getting in produced, not in big numbers though. Maybe classical web development can become such a craft too. Loved by some. > bilsbie: Someone should make a new internet modeled off of around 2002. > chasd00: Bind to port 81 and go for it. Our business here depends on professional PHP web developers in need for web hosting. We are not aiming for world domination. A small niche is fine for us. But it will be harder to find that niche. # Sudden traffic peak Source: https://blog.fortrabbit.com/case-study-sudden-traffic-peak Created: 2013-06-30 20:07:19 Author: Oliver Stark Tags: opinion > A case study of an agency site hit by a sudden traffic peak, what broke, and how the hosting setup was adjusted while it was happening. ## How to survive a sudden traffic peak Usually you can see your App's traffic and performance developing over time. So you have plenty of time to tweak your application and to adjust your setup. But how to be prepared for a sudden traffic peak? Our client Peter Gombos runs a web agency ([kriek](http://kriek.hu/)) in Hungary with focus on developing facebook apps. He asked us: > We are developing a web application [...] and would like to get a recommendation for a setup for the following: There will be a live voting during the "[Viva Commet](http://www.vivatv.hu/specials/comet/2013)" live event [...] approximately 200k users will use the app in a 3 hours time frame. He has built a straightforward voting app: [Slim Framework](http://www.slimframework.com/), Facebook connector and a Mysql Backend. We suggested to avoid massive the I/O on the database and the file system. So he added a [memcache session handler](http://fortrabbit.com/docs/how-to/memcache/memcache-in-redundant-mode) and a tiny caching layer in front of the DB. For the day of the event he scaled up his setup: #### Setup * **Startup 6 HA** (24 PHP-FPM processes) * **MySQL 20148** (32 connections) * **Memcache 512** (redundant) #### Stats for the voting period (3 hours) * PHP requests per second: ~75 (peak) * number of static requests: 1.5M * avg PHP response time: 150ms * memcache(d) hit rate: 83% #### Final words from Peter > Hey guys, just wanted to say thank you again for the great service you've provided thru the whole project. It was great to have someone in the background who we could count on! #### Our final words Thank you Peter for this real world benchmark. It was real fun to support you. For everyone interested diving even further: Our article [App design and optimization](http://fortrabbit.com/docs/in-depth/app-design-and-optimization) is a comprehensive guide that helps you to optimize your application and to understand our platform. # Celebrating one year of fortrabbit Source: https://blog.fortrabbit.com/celebrating-one-year-of-fortrabbit Created: 2013-10-04 Author: Frank Lämmer Tags: chronicles > One year of running a PHP hosting platform: a thank-you to the clients who trusted an unfinished product, and what comes next. As time flies by! It's already a year ago when we launched our PHP hosting platform here. I think we are doing good. Thank you so much for your trust in us. Thank you so much for all your help. Thank you so much for your feedback. Please keep it up. We are highly motivated to continue this journey. We've got lot's of cool stuff coming up. Enough talk, let's get back to work now. # Chasing 408 Source: https://blog.fortrabbit.com/chasing-408 Created: 2014-05-26 Author: Edgar Hipp Tags: changelog > Random 408 errors that appeared out of nowhere, and the hunt through load balancers and timeouts that finally explained them. Those nasty random "408 your browser didn't send a complete request" errors should finally be solved. Here's the story. We first stumbled on random 408 errors at the beginning of the month when Frank was showing us fortrabbit's newly designed landing page. An 408 error came up instantly. We first thought the problem came from a bad wifi connection. However, it occurred again under other conditions, but not on all of our computers and very randomly. Even more annoying, other sites hosted on fortrabbit seemed to be affected too. ### What's a 408 anyways? > 408 Request Timeout The server timed out waiting for the request. According to W3 HTTP specifications: "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time." So — the browser didn't send a request in time, now what? ### The errors were not logged by our load balancer It was quite hard to find what was going on — because the errors occurred very randomly and we didn't saw them in the logs. By then some clients reported the error as well. That pushed us to find a fix quickly. With the help of our clients we collected enough information to find out that the problem was only appearing in Google Chrome - WTF?!#. Other browsers were not affected. Still we couldn't reproduce the issue reliably. ### Provoking the error Finally I found an article about [Google Chrome's TCP preconnect feature](https://www.igvita.com/2012/06/04/chrome-networking-dns-prefetch-and-tcp-preconnect/)— this special feature opens connections for every link you're probably going to open to magically speed up things a bit for you. In other words: this smart Google Chrome browser immediately starts a connection whenever you hover a link and are still unsure you might want to click it. BTW: [InstantClick](http://instantclick.io/) is a similar approach based on JS. So the trick to reproduce the 408 error more frequently was to **wait before clicking a link**! BOOM ! 408 (sometimes). Those silently generated TCP connections are definitely not the normal expected behavior of a browser. ### Solving the issue and fine tuning the configuration Over the weekend, we increased the timeout value that is closing those TCP connections from 10 seconds to 30 seconds. Currently we are looking for the best value that doesn't throw 408 without affecting the load balancer's performance. Thanks again to everyone for reporting. # Chromopoly Source: https://blog.fortrabbit.com/chromopoly Created: 2025-09-15 14:44:24 Author: Frank Lämmer Tags: opinion > Chrome holds around 65 percent of the browser market. What that concentration means for competition, privacy and web standards. | Browser | Market share | | ------------------------------------------------ | -----------: | | Google Chrome | ~65% | | Safari | ~15% | | Microsoft Edge | ~5% | | Firefox | ~3% | | Opera | ~2% | | Other (Brave, Arc, Dia, Zen, Vivaldi, Samsung …) | ~10% | The current browser landscape shows how Chrome **chrominates**. This simplified view doesn't account for differences between mobile/desktop usage or operating systems. ## Love at first sight In 2009 authoring CSS was still playing mockawhole with Internet Explorer. Then Google Chrome arrived. It was lightweight and powerful. Everything Google produced was fresh back then. Chrome tookoff and helped to push web standards and to crack up the Internet Explorer dominance. It also pressured Apple to improve Safari (WebKit). I'm genuinely grateful for all of that. ## Under the influence of advocacy Over the years, I've become increasingly wary of new initiatives and web developer resources from the Googleverse. I don't click on search results from [web.dev](https://web.dev/) any more. Working in support with web hosting clients, I see developers chasing "best practices" according to Core Web Vitals (CWV) to improve their Lighthouse scores (SEO). This often leads to premature optimizations like above-the-fold CSS inlining while ignoring fundamental issues. It's classic over-engineering, but I also see Google's influence in it. ![Slide](/images/chrome-invents.png) Google Chrome team invents, but the rest of the web is just too slow. Slide from a recent talk by [Bramus](https://www.bram.us/) [YouTube](https://www.youtube.com/watch?v=njdiu83do0M). Other CSS heroes like Rachel Andrew and Philip Walton also joined the Google developer relations team. I hope they have a good influence. ### Google web platform innovations As a UI/UX person I am excited about new browser features like scroll animations and page transitions, or typographic improvments like `text-wrap: pretty`. But I can wait a bit until they will become standarized and mainstream available, specifically when there is a good fallback (progressive enhancement). Remember Houdini, the 'future' of CSS - back in 2016? Google's web team has delivered fails and genuine improvements, but some initiatives raise questions: - WEI - Web Environment Integrity API - AMP - Accelerated Mobile Pages - Permission element proposal - [Google blog](https://developer.chrome.com/blog/permission-element-origin-trial), [HN](https://news.ycombinator.com/item?id=44281633) ## In closing I keep using Firefox with uBlock Origin (hello Manifest V3). But it should not be forgotten that Firefox major revenue source (75%?) is for the default search engine deal with Google. I'd like to see an open, decentralized internet. I believe a diverse browser ecosystem means better security, more innovation and stronger privacy protections. I've read about growing influence by tech giants on web standards through WHATWG and W3C, but I lack insights. Is it time for antitrust action? I don't know. Do I want to see want to see a new browser by an AI company that does not have a good track record in privacy? No, I don't. Up until, please remember to don't be evil. Thanks. # Is PaaS dead? Source: https://blog.fortrabbit.com/cloudscapes-rerevisited Created: 2016-01-13 Author: Frank Lämmer Tags: opinion > Is PaaS dead? Trends, pivots and troubles in PHP cloud hosting in 2015, seen from inside one of the companies competing in it. In my [first article](/comparing-cloud-hosting-platforms) about [PaaS hosting](https://en.wikipedia.org/wiki/Platform_as_a_service) — or aPaaS as Gartner likes to calls it — from July 2012 I explained the superior PaaS model and highlighted vendors from the US and Europe. With the [second article](/cloudscapes-revisited-php-cloud-overview) from May 2014 I revisited the scene — showcasing new participants and describing some struggle. Spoiler: This is an opinionated post. ## News from the vendors **2015 has NOT been a good year for the PaaS scene.** No newcomers, lot's of exits and pivots. No PaaS provider was in the mood to publish an [end-of-year review](http://mailchimp.com/2015/) [microsite](https://www.campaignmonitor.com/2015/) with [vanity metrics](https://www.behance.net/yearinreview) and [fancy info-graphics](https://www.pingdom.com/2015). **[Heroku](https://heroku.com)** the PaaS category inventor made some notable changes in their pricing. Peter van Hardenberg [shared some insights](http://www.heavybit.com/library/video/2015-11-17-peter-van-hardenberg) on that long and windy road. The free usage got less attractive, paid hobbyist usage got more attractive. I find it notable that the hobby-pricing-level is competitive with DigitalOcean. **[Pagodabox](https://pagodabox.com/)** have launched a new dashboard release. Apart from that it looks a bit quit over there. Look twice: The makers are working on a new service called [Nanobox](https://nanobox.io). It's about parity between local development and production environments. Pretty much of it is open source. There is a desktop installer which integrates Docker & Vagrant and there will be some kind of management to deploy those applications to any cloud provider. **[Jumpstarter](http://jumpstarter.io/)** was closed. They have made made many pivots in business model and strategy, each of them was interesting. **[cloudControl](https://www.cloudcontrol.com/)**, our fellow travellers from Berlin, just recently filed for bankruptcy. In the [article on Gruenderszene](http://www.gruenderszene.de/allgemein/cloudcontrol-insolvenz) (in German) we can read that there is a good chance that service will be continued however. **[Nodejitsu](https://www.nodejitsu.com/)** "the original Node.js platform as a service" exited the PaaS business, the team has joined GoDaddy instead. **[Shelly Cloud](https://shellycloud.com/)** a Ruby cloud from Poland closed their doors. **Relbit** (EviaCloud) a Chezch PaaS also closed without much notice. **PogoApp** are currently [pivoting](https://twitter.com/pogoapp/status/683064343865475074) towards managed PaaS/IaaS hosting vs. DIY public PaaS. ## Trends in PaaS **PaaS has become an f word**: It seems like the word PaaS already sound old, so most vendors have stopped calling themselves so. **Transparent pricing**: droplets, processes, dynos — each PaaS provider has had it's own obscure units. Not any more: You will find explicit specs in MB everywhere. Developers want to know what they are buying. A find this trend a bit dangerous as PaaS is not only about MB, but also about service. The EngineYard pricing page has two dropdowns. On the left the price for their platform (& support), on the right the price for the infrastructure. I think that's a great design as it separates service from the hardware. **Choose your cloud**: Some PaaS vendors let you choose the underlying infrastructure. Decide yourself, if your App shall run on AWS, DigitalOcean or Vultr. Still you only pay the PaaS. [Modulus](https://modulus.io/) and [Cloudways](http://www.cloudways.com/en/) are doing it like so. **Bring your own cloud servers**: I call this a meta-PaaS, where service and infra are separated. The pricing is clear, you pay to use the software, freedom to choose your own infra. You pay two bills. Sample providers are: [Cloud66](http://www.cloud66.com/), [ServerPilot](https://serverpilot.io/), [Laravel Forge](https://forge.laravel.com/), Nanobox (see above), [PuPHPet](https://puphpet.com/) (Open source). The advantage for the provider is, that it takes less efforts to build and maintain such a service. I see some potential problems in responsibilities: The client signs two contracts. There is a grey-zone between the two services. ## My conclusions I am biased. I still believe that the original Platform as a Service is a legit model. Object orientated hosting with a high abstraction level is actually nice. [Did Docker kill PaaS?](http://www.theregister.co.uk/2015/06/01/did_docker_kill_paas/) Docker was originally build for a PaaS, as PaaS is making use containers. Docker is about orchestration of container based cloud hosting infrastructures. Docker transforms SysOps to DevOps. PaaS abstracts away containers, so developers can focus on coding instead of managing containers. PaaS is NoOps instead of DevOps. VPS is only cheaper when developers forget that their own time has value as well. ### So why is PaaS not taking off when it is "better"? I think it's a lot about the developers mindset and modern hosting services is about developer happiness. ### Tinkerers from the heart ![Tools by Jürgen Schiller García](/images/2508086911_4ef818b3f1_o.jpg) Developers are problem-solvers. They love to play with tech. Mastering complicated tasks is a sport to them. Every developer is building her/his own very best hosting solution, even when it takes lot's of time and the result isn't production-grade. _"Hey developer, hosting is broken, we have solved all the SysOp tasks for you, so that you can focus on code now!"_ _"Hey PaaS, thanks i am already fine with my own setup."_ _"But your setup sucks! Look, ours is much smoother!"_ _"Shut up PaaS."_ ### Communication & fit Developers don't see enough value in PaaS. I believe that this is a communication problem. Our perspective is, the longer the clients stay, the more they like our platform. It also is a product-market-fit problem: N00b developers really need PaaS as they don't know about Ops at all. But PaaS employees don't like to toy around with n00bs. N00bs don't have the money to afford anything else than the freemium plan anyways. The junior developers are in between but are already hooked by doing SysOps themselves. The mid-level developer knows exactly which exotic special dev tool is missing in your PaaS. The senior developer actually has grown needs for this kind of architecture and team. PaaS is a black-box; it's proprietary; it's a beautiful island; it's not as versatile as a home-grown solution. Developers love the freedom of root access, they want to able install any open-source software they like. While PaaS is offering well defined and thoughtful solutions. ### Price sensibility Hosting is by tradition about hardware resources — not so much about value of service. It's a commodity. People expect it just works, there is no quality of service. So developers go to the cheapest store to buy it. They compare providers by prices. Now, when developers don't really see a big value in a managed hosting platform, why pay more? It's tough. A competitive or even aggressive price would probably help. But PaaS are often using IaaS instead of running own hardware. We for example use AWS, so we buy some resources at a higher price than they are sold by the next VPS provider. ### DigitalOcean VPS hosting is not a distributed resilient system of loosely coupled components. It's just an empty box. You are supposed to put everything inside — and build it yourself. But yet, they have 214k web-facing computers, and usually more than 6000 new ones each month ([Source: NetCraft](http://trends.netcraft.com/www.digitalocean.com)). So they must do something right. It's affordable and hackable. ## Our stake in the game Thanks for asking. fortrabbit is doing OK. We don't have plans to close down anytime soon. We haven't accomplished all of our goals in 2015 but I don't blame the industry for that. We'd like to do things right and that sometimes takes a little longer. I strongly believe that PaaS is a good idea, we do our best to execute it right. We learned a lot in the past three years and we are eager to go on. Tools photo Jürgen Schiller García via [flickr](https://www.flickr.com/photos/schillergarcia/2508086911). **Thanks for your interest!** Lot's of comments over at [HN](https://news.ycombinator.com/item?id=10894624) and on [Reddit](https://www.reddit.com/r/programming/comments/40sfr7/is_paas_hosting_dead/). # Cloudscapes revisited Source: https://blog.fortrabbit.com/cloudscapes-revisited-php-cloud-overview Created: 2014-05-19 Author: Frank Lämmer Tags: opinion > A subjective insider tour through the PHP cloud hosting scene of 2014: who arrived, who struggled, and what changed since 2012. About two years ago i published "[Cloudscapes — comparing PHP cloud hosting platforms"](/comparing-cloud-hosting-platforms). I think it's a good time to revisit the scene. Note: This is a totally subjective insider view. We are a PHP cloud hosting provider ourselves, that's why **fortrabbit** is not included as a third-person singular in this list. The boundaries are blurred. There is not really a PHP cloud hosting category, i have just included everything that looked interesting to me as a developer / startup guy. ## Past participants **[Heroku](https://heroku.com)** invented the PaaS category, so it's natural to name them first. [Very recently](http://techcrunch.com/2014/04/29/heroku-bets-big-on-php/) they finally catched up and made a big step forward being a true PHP PaaS with native Composer support and HHVM integration. To make PHP really fly, they hired [David Zuelke](https://twitter.com/dzuelke). I think the big picture here is: Laravel is to PHP now, what Ruby was to Rails a few years ago. Heroku proofed to be past, present and future of PaaS. **[AppFog](https://www.appfog.com/)** made a lot of waves in the PHP community back then, then they transformed to AppFog, then they got bought by CenturyLink, then they ditched their free plans. Maybe i am wrong, but it looks a bit silent over there, maybe they are doing something else, maybe they just keep calm and do their business? **[Pagodabox](https://pagodabox.com/)** is working on a new dashboard interface for quite a while now. I had the chance to sneak-peak it — looks promising and really really stylish. **[dotCloud](https://www.dotcloud.com/)** made a 540deg turn. As far as is read the story: Like AppFog (and us in the future), they ditched the freemium plan. Alongside they open-sourced a core component of their platform: Docker (LXC made easy). Docker went boom. DotCloud pivoted and became [Docker.com](http://docker.com) offering B2B solutions services around Docker. Alongside a new category was born: Docker as a Service with commercial services like: [Flynn](https://flynn.io), [Stackdock](https://stackdock.com/), [Deis](http://deis.io/), [Orchard](https://www.orchardup.com/), [Tutum](http://www.tutum.co/), [Appsdeck](https://appsdeck.eu/) … A really interesting story about combining open source and business. **[cloudControl](https://www.cloudcontrol.com/)** keeps calm and continues to make business. Similar to [Jelastic](http://jelastic.com/), they are also offering a [white label PaaS](http://www.whitelabelpaas.info/) solution. **Relbit** is now [EviaCloud](https://eviacloud.com) and EviaCloud is part of Relbit and it seems to be evolving. **Stackblaze** is no more. **[Clever Cloud](https://www.clever-cloud.com/en/)** is doing fine, seems to me. **Omnicloud** needed some more time to finally launch. It's called [Jumpstarter](http://jumpstarter.io/) now and is up and running. UPDATE 2014/07: [Jumpstarter closed](http://blog.jumpstarter.io/jumpstarter-is-evolving) their platform to focus on something new. After **[Engine Yard](https://www.engineyard.com/)** acquired Orchestra it took a while until they finally integrated everything to one seamless service. The transition is over and everything looks very smooth, on an enterprise level. ## New kids on the block **[Viaduct](http://viaduct.io/)** will launch in June. **[Laravel Forge](https://forge.laravel.com/)** was the big announcement Taylor Otwell (creator of the Laravel framework) made very recently on Laracon NYC. I would describe it like this: Actually not a real hosting service — more like a meta-service (SaaS) bringing together your development environment and your hosting services. Naturally it's coupled (but not limited?) to the Laravel framework. [PuPHPet](https://puphpet.com/) or [ServerPilot](https://serverpilot.io/) are similar services. **[Bowery](http://bowery.io/)** is another new interesting service, aiming to simplify setup of development environments. **[AnyNines](http://www.anynines.com/)** based on Cloud Foundry also supports PHP (see comments below) is still in Beta but looks very promising — from the makers of [railshoster.de](http://www.railshoster.de/). ## All the others [GetPantheon](https://www.getpantheon.com/), [CloudProvider](http://www.cloudprovider.net/), [JiffyBox](https://www.jiffybox.de/), [GetUp cloud](http://getupcloud.com/index_en.html), [Acquia](http://www.acquia.com/), [Google App Engine](https://cloud.google.com/products/app-engine/), [OpenShift](https://www.openshift.com/), [AWS](http://aws.amazon.com/), [Windows Azure](http://www.windowsazure.com/), [Rackspace](http://www.rackspace.com/), [CloudSigma](https://www.cloudsigma.com/), [ElasticDot](https://elasticdot.com/), [Fused](http://www.fused.com/), [CityCloud](https://www.citycloud.com/), [Little Orange](http://asmallorange.com/) and of course [Digital Ocean](https://www.digitalocean.com/), [Linode](https://www.linode.com/), [WebFaction](https://www.webfaction.com/), [Media Temple](http://mediatemple.net/), [NearlyFreeSpeach](https://www.nearlyfreespeech.net/) and even [GoDaddy](http://www.godaddy.com/), [Hetzner](http://www.hetzner.de/en/) and that's still just the tip of the iceberg, because that is just the english speaking side of the world and these are only the offers for developers. There are also services targeting the needs of consumers without HTML-skills, designers or enterprises (top-down approach). ## Now what? You — as a developer — have more choice than ever now, cool. We — as an "old service" — are of course scared as fuck by the new competition from all sides. But hey, let's embrace it. New entries in our market segment are proofing that we are on the right track. We have a cool service and we got cool stuff in the pipeline. # CMS, quo vadis? Source: https://blog.fortrabbit.com/cms-quo-vadis Created: 2015-10-09 Author: Oliver Stark Tags: opinion > Content management systems went quiet in the PHP conversation. Are they ready for the cloud, and what would that even require? ## Are content management systems ready for the cloud? I follow general discussions about PHP in podcasts, on Twitter, on [Reddit](http://www.reddit.com/r/php) and on sites like [phpdeveloper](http://phpdeveloper.org/) or [phptoday](https://www.phptoday.org/) a lot. And I wonder **why content management systems are not a topic these days?** It seems like that they don't exit anymore. People talk about PSRs, APIs, design patterns, Composer packages and frameworks. Most of our clients are building applications from scratch, usually on top of a framework like Symfony, Laravel, Slim or Phalcon. [Our Twitter stream](https://twitter.com/fortrabbit) is dominated by these topics as well. Let me backtrack a little first: Before we started fortrabbit we ran a digital agency for about 8 years. We did jobs for small and large clients. We touched many technologies to manage content in the web: from plain PHP to CakePHP, Magento, Drupal, Fatwire (Java) and last not least WordPress of course. I was wondering what have changed. So, I did some research to update myself. Surprisingly most of the CMS projects still exist. They evolved, some more, some less. And there are even many newcomers out there. Here is a short overview of my (superficial) investigations: ## Established CMS platforms Most of the large FOSS projects exist over a decade now and have matured over time. They have created their own developer communities and their own (isolated) ecosystems of plugins or modules to extend the core functionalities. Specialized agencies or consultants with deep knowledge are usually required to build websites on top of these platforms. To stay relevant almost every established big platform releases a new major version every 3-4 years. Currently it's not so much about new features. There is a movement towards [interoperability and standard compliance](http://www.php-fig.org/) now. ### Drupal Drupal is problably the most popular CMS in the US, however the founder Dries Buytaert is from Belgium. When I worked with Drupal for the first time version 7 was in beta. Multilingual support was a project requirement. It turned out that 6 modules were required to translate all bits and pieces. Additionally the whole architecture with render arrays and hook functions felt weird to me — I wrote OOPish code before. Now, about 5 years later, Drupal 8 is in beta/RC and [moves quickly towards stable](https://drupalreleasedate.com/) - this time with i18n support in core. But more importantly it feels like a modern PHP application. There is less proprietary stuff to learn, when you've worked with Symfony components like HttpKernel, Twig or Routing before. Drupal 8 is still a complex beast, but there are tons of educational resources out there. Another plus is the huge community of developers with a decent level of knowledge. Chances are high someone else had a similar problem before and *There is a Module for That*™. ### eZ Publish / eZ Platform For a long time eZ mainly targeted the publishing industry. This was reflected in the name of the core product: eZ Publish. In 2015 they changed the focus by introducing [eZ Platform (free) and eZ Studio (commercial)](http://ez.no/Blog/What-Releases-to-Expect-from-eZ-in-2015). Both software products use the same kernel, based on Symfony Framework 2.7/3.0 and [other libaries](https://github.com/ezsystems/ezplatform/blob/master/composer.json) like flysystem, doctrine/dbal and stash. "Alpha4" of eZ Platform (aka eZ Publish 6.x) was released some days ago, so it might take some time until it becomes production-ready. But the current stable version (5.4) already looks quite modern and is officially [supported until 2017](https://support.ez.no/Public/Service-Life). ### Typo3 / Neos Typo3 is/was the first choice for many European web agencies. For many years it was the OSS defacto standard solution for German government and NGO websites. My personal experience with Typo3 is very limited. The latest version of Typo3 CMS (7.5) looks quite modern: It [requires PHP 5.5 or later](https://git.typo3.org/Packages/TYPO3.CMS.git/blob/HEAD:/INSTALL.md), integrates with Composer and has a proper file system abstraction layer. But there are also Flow and Neos. Backed by the TYPO3 Association, Robert Lemke and Karsten Dambekalns started a complete rewrite known as Typo3 Neos (based on the flow framework) around 2008. Both branches are co-existing under the Typo3 umbrella for years and are actively maintained. This led to confusion for newcomers. However, recently with the 2.0 release, Neos (without the Typo3 prefix) is run independently. It seems to me that this move frees a lot of energy in the community. Neos 2.0 and Flow 3.0 (< this is the version number) aim to be ready for the cloud and try to [liberate from the Typo3 legacy](https://www.neos.io/news/infrastructure-for-our-community.html). ### SilverStripe SilverStripe is the PHP CMS with the biggest popularity in New Zealand and Australia. [A new major version (4)](http://www.silverstripe.org/blog/sneak-peek-silverstripe-4/) is on the way. SilverStripe 4 should be better integrated within the PHP ecosystem: by leveraging other 3rd party libraries like flysystem or Swift Mailer, but also by decoupling there own underlying framework and splitting it into reusable packages. SilverStripe 4 is expected to be released in 2016. For the current version (3.1 / 3.2 beta) I found two modules to support S3 file storage: [silverstripe-cloudassets](https://github.com/markguinn/silverstripe-cloudassets) and [silverstripe-s3cdn](https://github.com/silverstripe-australia/silverstripe-s3cdn). To my surprise [Christopher Pitt](https://twitter.com/assertchris) moved to New Zealand and joined the team earlier this year. To me this is a good sign hiring a forward thinking member of the PHP community and I hope this will drive forward the cultural change in the SilverStripe community. ### pimcore The first time I heard of pimcore was at the local [Berlin user group](http://www.bephpug.de/slides.html) in 2012. Christoph Luehr introduced is as the CMS he uses [at work](https://basilicom.de). During my research I've installed the latest version (3.0.6) and tried to configure the system. But I was stuck at some point - probably not pimcore's fault - complexity lies in the nature of "enterprise software". **Me:** pimcore is build on top of ZF1. Can we expect a change towards ZF3 in the future? **Bernhard Rusch, CTO / Co-Founder of pimcore:** We will replace many components we've build inhouse and ZF1 components as well with modern libaries. This means pimcore will not be tightly coupled to a specific framework anymore. Instead we'll use mature libraries from different vendors - this process will happen step by step. Bernhard Rusch mentioned as well that the next major version is expected for mid 2016. A early pre-release was [annouced last month](https://www.pimcore.org/en/resources/blog/pimcore+4+beta+announcing+the+first+public+pre-release+of+the+open-source+enterprise+suite+for+pim%2c+cms%2c+dam+%26+commerce._b13633). ### WordPress According to W3Techs Usage statistics: WordPress powers 24% of the internet — an [impressive number](http://w3techs.com/technologies/overview/content_management/all). It means that Wordpress is one important factor for the huge market share of PHP. At the same time it is responsible for the bad reputation of PHP (we have lamented about that before). The minimal required PHP version is still 5.2, that version was released 9 years ago and is unsupported for almost 5 years. Modern language feature like namespaces, traits and anonymous functions are not availiable in PHP 5.2 - and that's how the core looks like. The strategy of small iterations might be a good thing, but it also keeps a lot of legacy in the code. Matt Mullenwegs [keynote talk at WordCamp Europe 2015](http://wordpress.tv/2015/07/04/matt-mullenweg-keynote-qanda-wordcamp-europe-2015/) gives you are good picture about it. Despite all the criticism one have to admit that only some tweaks and [plugins are required](http://de.wordpress.org/plugins/search.php?q=s3) to run Wordpress in the cloud already. ## CMS Newcomers The newcomers are less bloated and not as "feature complete" as their bigger brothers. They aim to solve smaller problems with simpler solutions. This approach works good for small to medium sized websites, marketing campaigns or for clients with smaller budgets to just edit some pages. ### Pagekit There was some buzz about [Pagekit](http://www.pagekit.com/), when the folks at [YOOtheme](https://yootheme.com/) (the company behind Pagekit) launched the first public alpha in July 2014 — 2 years of development behind closed doors. During the last months the initial wave of excitement turn into silence. But then, some weeks ago, the [first beta appeared](https://pagekit.com/blog/2015/09/10/pagekit-beta-released) - a complete rewrite, with new a Vue.js based user interface and a CLI for scaffolding. Things may change until the 1.0.0 release and there are still some important features missing — like custom fields, multi-language and cloud storage support. Nevertheless, it is a project you should keep an eye on. ### Bolt CMS Bolt 2.0 was released about 10 months ago - the main code contributions come from [Two Kings, a dutch agency,](http://www.twokings.nl) who founded the CMS in 2012. During the last months an increasing number of people are using Bolt and are contributing to the project as well. As I had no experience with Bolt, I gave it a try. There are to ways to install it: 1) composer create-project, 2) .zip file download (for shared (FTP) hosting). I've tried both, the Composer way feels much better to me. The Composer based skeleton is basically a `/public` folder with a `index.php` file and some static assets, and a `/app` folder where config and cache lives. All other dependencies, including Bolt itself, are in the `/vendor` folder. The bootstrapping and the configuration is pretty straight forward - there is not much new stuff to learn if you've worked with Silex and the Symfony Config Component before. The configuration is .yml based, environment specific configs are possible and for edge cases you can overwrite settings on the fly in PHP. Filesystem abstraction is advertised with the 2.0 release, [but it's not fully implemented](https://github.com/bolt/bolt/issues/4095) - the only available adapter is the LocalAdapter. It would be really nice to see alternatives like S3 as an configurable option, or at least an [extension](https://extensions.bolt.cm/). ### Craft CMS Craft differentiates in two ways: First: except for the Twig template engine, Craft CMS is not built on top of Symfony components. The underlying framework they use is Yii. And second: itˋs not free open source. You can try all aspects during development, a limited personal edition is free as well, but for commercial usage a (small) one time license fee is required. This way the maintainers assure further development and bugfixes. The company behind Craft is called Pixel & Tonic, a dev shop from US with experience in consulting and EE extension development. They started their own software about two years ago. Craft is quite popular in the (US) EE scene, but largely unknown in Europe. However, some of our clients from the UK use it and are very happy with it. I've installed [the developer preview](http://buildwithcraft.com/3) of the upcoming version. The configuration was a no-brainer. By default it supports multiple environments based on the domain it runs on, but it was fairly easy to detect the environment by ENV variables (a common practice these days). I haven't tried to upload media assets, but under the hood it works with our good friend [flysystem](http://flysystem.thephpleague.com/). The next major release (Craft 3) adopts PHP language features like traits, namespaces and late static bindings. And everything feels quite modern, except the lack of using Composer. But that might change in the future. ### All the others Further more I have also checked out: Joomla! (veteran), asgard CMS (L5.1), october CMS (L5.0), Grav (flat file), Fork CMS, PyroCMS (3.0, L5.1), sulu CMS — but enough for now. ## Is your CMS ready for horizontal scaling? Running a content management system "in the cloud" requires not much effort these days — since most modern CMS are prepared for that case. An important aspect of cloud hosting is that multiple copies of your code spread across multiple machines - known as horizontal scaling. The main difference to a single VPS you must be aware of: The only thing which lives in the web-servers file system is your code. You can not rely on the local file system to avoid inconsistent session states. Sessions must be stored centralized, in an external database — think Redis or Memcached. The same applies to the application cache. And finally, all user uploads must be offloaded to a central place - AWS S3 or Rackspace Cloud Files are a good choice for storing and delivering images, music or any kind of static assets. If you roll your own cloud setup at AWS, Rackspace or Digital Ocean you must implement some kind of load balancing, a centralized logging and a way to [distribute your code](http://help.fortrabbit.com/deployment-architecture-video). Erika Heidi did a [good introduction](https://www.digitalocean.com/company/blog/horizontally-scaling-php-applications/) on that. You should read it to understand the benefits and implications of horizontal scaling. With managed cloud platforms like Heroku, Google App Engine, Microsoft Azure and fortrabbit as well, you don't have to care about the whole infrastructure layer. ## Final thoughts Back then, I preferred to build custom back-ends on top of frameworks, instead of using a CMS to manage dynamic website content. This approach wasn't very efficient, but it was owed by the fact that the editor experience of open source content management systems was really bad. To enable editors managing content on their own, intensive trainings were required. Fortunately this changed, user experience becomes more and more important. For agencies and developers, 2015 is the right time having a closer look at the new solutions out there. There is no single best CMS. Instead, each product has a mix of strengths and weaknesses that are derived from its underlying architecture or market position. My suggestion: Invest a decent amount of time to evaluate software you may use for the next 5-10 years. Don't trust feature lists and the marketing! Choosing a CMS is crucial business decision: It's about technology, concepts, maintainability, predictability, the developer community and not least about attracting future employees and clients. ## Bonus And here is a video of me painting the logos: # Cold outreach Source: https://blog.fortrabbit.com/cold-outreach Created: 2026-03-10 11:01:03 Author: Frank Lämmer Tags: opinion > An inbox full of AI-written cold outreach, collected over weeks and read closely. What the most sophisticated spam so far looks like. The following AI cold contact mails have been collected over a few weeks, slightly edited (removed names, line breaks, em-dashes and typographic quotes). ## Hi Frank > just put together a pre-hire simulation for Fortrabbit to assess how your applicants will execute tasks they'll actually do on-the-job (no quizzes or multi-choice fluff) It will generate a demonstrated skills scorecard based on each candidate's performance, cutting days in pre-screening and interviews. Should I send over how it works? P.S. Bloomberg, EY & Athena have increased candidate conversion by 3x. > I'm writing to share a high-impact opportunity for Fortrabbit to secure partnerships with the biggest names in the food and beverage industry. Our upcoming European Food Manufacturing Summit gathers a curated audience of over 120 senior executives from companies like Ferrero, Mars, Mondelez, Unilever and more. We believe this is the ideal environment for you to bypass the gatekeepers and network directly with top-tier decision-makers. A key highlight of this sponsorship is the opportunity to speak on Day 2 in front of over 120 decision-makers, as well as to host a Lunch & Learn with 10 senior executives who select your table, allowing you to lead the conversation and demonstrate your value directly to potential partners. Let's ensure your organization starts the year with a strategic advantage. Are you free for a brief 15-minute chat next week to walk through the details? > Following up to see whether Fortrabbit has any projects for 2026 that may benefit from additional engineering resources or expertise. Our professional services include Dedicated software development teams, Custom software development, Software audit and Software maintenance. With 96% senior engineers and ISO 27001 / ISO 9001 certified processes, we ensure secure, reliable, and high-quality delivery. When applicable, we accelerate development using our in-house solutions, including: Data collection platform, Data quality checker, Dashboard UI components library, Mobile kit for building control apps. These tools help shorten development timelines while maintaining consistency and quality. Would you be available for a short conversation to see if our expertise could support your 2026 goals? > We launched a tool that lets you be SOC2/ISO2701/HIPAA compliant in record speed. In June this helped Capgo become SOC2 compliant in <24h & they got their attestation just 9 days later. Respond 'yes' if you'd like me to send you a signup link. > I wanted to follow up on my last note in case it got buried in your inbox. We've been helping companies like Fortrabbit quickly scale their dev, design, and marketing teams with pre-vetted remote talent, and I'd love to show you what that could look like for your team. No long hiring cycles or hidden fees, just great people, ready to plug in and deliver. If you're open, I'd be happy to share a few profiles so you can see the quality firsthand. Just let me know! Looking forward to hearing from you. > We help SaaS founders recover failed payments and improve retention automatically. Would you be open to a short chat to see what we could unlock for Fortrabbit? > I see Fortrabbit.com is DR 61 and 372 traffic/mo on Ahrefs. I call it a good takeoff, but is SEO a priority in Q1 '26? If yes, we'd love to slide in. We specialize in SaaS SEO and SaaS SEO only. Links, contents and technical SEO, we cover all 3 grounds of it. > I hope this note finds you well. I came across Fortrabbit and I think we can collaborate. At XXXX, we help startups and growing companies scale quickly with skilled offshore engineers, designers, and digital experts, often at up to 5x lower cost than local hiring. To make it risk-free, we offer a complimentary 20-hour trial project so you can experience our team's work before committing. Would you be open to a short call to see if this could support your goals now or in future? > Quick question, would you pay $100 per qualified sales meeting? In the past, I would in a heartbeat... Until this software started producing them for $11.70. 10,000 of them in fact. (My sales reps think Im a fucking wizard). It breaks the agency and paid ads model. It researches hundreds of prospect data points & 'Glove Fits' emails at scale Launches to 150k dream prospects, 2 minutes after signing up. Does everything with AI, after it gets to know Fortrabbit. There is no contract. It is the same price as a fancy dinner. There's also a free trial! (Don't share this with anyone) > Are you guys adopting an AI strategy currently? We would love to exchange some thoughts with you on that. No harm in having a quick chat on Teams or Zoom? > I'm currently on Fortrabbit.com - Your company is potentially leaving five to six-figure funding amounts on the table, often without your knowledge. We have been successfully supporting companies for over five years in applying for research grants and I just learned about your MySQL 8. The chances are good that we can secure funding for you, I have one or two quick follow-up questions about that. I would already prepare a calculation for you, showing exactly what funding amount you can expect, let's have a quick phone call in the coming days. When would be the best time to reach you? > We've put together a customer acquisition infrastructure that scales like ads with 0 ad spend. Your offer gets put in front of 10,000+ ideal clients each day. Sounds interesting? > Following up briefly to highlight that our experienced developers can help you leverage AI agents to revolutionize operations in your managed cloud hosting platform for PHP applications by streamlining Git deployment to reduce downtime, intelligently managing server resources for optimal performance and cost efficiency, automating troubleshooting for faster resolution times, and enhancing security protocols to protect against vulnerabilities. I'm interested in discussing how AI agents are revolutionizing operations in the Information Technology industry. Nestack Technologies empowers businesses to develop and deploy AI agents for complex tasks, seamlessly integrating them into automation workflows. > We are inviting your esteemed company for vendors registration and intending partners for Abu Dhabi National Oil Company (ADNOC) 2025/2026 projects. These projects are open for all companies around the world, if you have intention to participate in the process, please confirm your interest by asking for Vendor Questionnaire and EOI. We appreciate your interest in this invitation and look forward to your early response. > This is my last email. If you're spending 6-8 weeks to hire a developer, you're losing money. Each week a role remains unfilled is a week you miss out on new projects. It's an opportunity cost you can't recover. In 72 hours, our hiring automation system identifies, qualifies, and technically evaluates candidates. $0 for your next hire. You only pay if you actually found someone useful. If you need to scale your team faster, reply to me with a good time. Otherwise, best of luck with job boards. > I know it's the weekend and this email is probably sandwiched between brunch plans and ignoring notifications (respect!). I'll keep it short and skip the salesy jazz. We're not an average IT shop. We build custom software, top-tier cybersecurity, seamless integrations, and AI/ML solutions tailored to your business goals. We've been at it for 18+ years, with teams in 30+ countries. If you're curious, we can hop on a quick 15-minute call with case studies and real-world results in hand, no fluff Interested in a call next week? I promise we'll keep it useful, no PowerPoint pain. What do you say? > Apologies for reaching out directly to your inbox. We are offering you free access to our 2026 AI Strategic LMS software — an easy-to-use and customizable platform that automates daily tasks assigned to Chief Executive Officer at Fortrabbit, in a single click. Would you spare 30 seconds to watch the process video walkthrough over email? > I really appreciate the opportunity to connect with someone from your Company. At XXXX, we help businesses accelerate growth through AI agents, custom software, workflow automation, low-code apps, and real-time dashboards built to fit any industry. We're currently offering POC so you can explore how our solutions can optimize your operations and boost efficiency. Would you be open to a quick call next week to discuss? > I took a look at Fortrabbit and immediately had an idea how you could predictably get more meetings with ideal clients. Can I show you this briefly? Takes less than 5 minutes. PS: If relevant - comes with a guarantee. > We can improve Fortrabbit's customer engagement through tailored communication, enhancing sales conversions and reducing lead time. Mind if I forward some information your way? > Just wanted to check in and see if Fortrabbit already uses any tools built on stripe to recover failed payments or improve trial conversions. If not, I can share what other computer networking founders are doing to recover 15% to 40% of lost revenue automatically, especially companies that operate as a managed cloud hosting platform for php web developers and agencies. Would you like me to send over my calendar? > Big news in your space. Anthropic just acquired leading developer tool startup Bun. Buyer interest in software publishers is surging, and companies like yours are in high demand amongst the investors. Recently, two investors missed out on a business similar to yours and are actively looking to acquire in your niche. At XXXX, we've closed 1,500+ SaaS and digital services deals. Right now, we're offering a free, no-obligation valuation for founders exploring their next move. Interested in seeing what Fortrabbit could be worth in today's market? Let's talk. > Was wondering if you'd be interested in learning more about a pre-hire simulation we built for Fortrabbit that helps you identify top performers early and cut your screening time by almost half? > I wanted to follow up on my last note in case it got buried in your inbox. We've been helping companies like fortrabbit quickly scales their dev, design, and marketing teams with pre-vetted remote talent, and I'd love to show you what that could look like for your team. No long hiring cycles or hidden fees, just great people, ready to plug in and deliver. If you're open, I'd be happy to share a few profiles so you can see the quality firsthand. Just let me know! Looking forward to hearing from you. > Frank - Noticed you sell to web developers to offer them PHP hosting as a Service. With XXXX AI, you can send personalized emails to them directly at scale. (And we have so much data on these groups specifically.) It's the simplest and most cost-efficient way to fill top-of-funnel - without bringing on more staff. Worth discussing? > Figured you didn't start your php cloud hosting platform just to stop booking calls every time client work ramps up. Not sure if it's a fit, but we've helped over 400 scale their 'Zero-Ad Scaling Blueprint' using a tool without extra effort, head count or complexity. Specifically, I think it could help you build a repeatable social proof system that uses Shealan Forshaw's success to trigger both direct replies and inbound leads from developers frustrated with traditional hosting solutions. If you'd find more info on this system useful send a simple 'yes'. > I took the liberty of creating a fully functional Ai rep for Fortrabbit using your public knowledge base. It is trained to resolve routine inquiries, drastically reducing backlog. Open to a quick walkthrough? > I came across your LinkedIn profile. I noticed that fortrabbit.com often doesn't appear at the very top on Google & ChatGPT. How about a short, free SEO & GEO workshop? We'll look at what you can do better and give you concrete tips immediately. I look forward to your feedback! > I don't know which employee benefits you are already using at Fortrabbit. But you can now access well over 400 attractive health services that are really well received - depending on what goal you are pursuing. Particularly popular: Specialist appointment service at private level, massage, osteopathy, physiotherapy, glasses and dental supplementary benefits, psychological prevention. Most companies use these benefits for employee retention, fewer sick days, or to attract new talent. Often in combination with government funding. The easiest way is if we briefly discuss which benefits are most worthwhile for you. Feel free to send appointment suggestions or get in touch briefly, then I will send you some. > If you're more focused on growth than a sale right now, we'd be happy to connect you with VCs actively investing in your space. We support both exits and capital raises our investor network spans strategic acquirers, PE firms, and growth-stage VCs. Would you like a few warm intros? > I hear this statement from IT managing directors again and again: "How much time do I have to invest with you to win new customers?" The honest answer: A single video from you, we take care of the rest. After that, the system runs automatically and generates appointments in your calendar while you go about your daily business. In the video I already sent you, you can see exactly how we implement this and how you can win new customers in a predictable way. > Wanted to let you know that you're doing something good. I stumbled upon fortrabbit through ChatGPT, man. Pretty awesome. I'm reaching out because I was wondering if you'd be interested in a white-label AI chatbot for your clients, which you can deploy or upsell your existing clients again and again with one click? I think you could easily add $1k-$5k per client to your revenue stream with this ready-to-go solution. I can help you set this up for one time and only pay when you actually make an upsell. My background, I help local businesses implement AI to increase their productivity and revenue. What do you think?. > I hope you've been doing well. I sent you an email a few days ago regarding ISP's and MSP's Decision makers but haven't heard back from you yet, May I share a few sample contacts and the price list for your review? Kindly reply with the details below: > If selling isn't a current priority, that's absolutely okay. I'd be pleased to provide a current valuation of your organization, a forecast of its future price if specific problems are optimized, and the steps you may follow to enhance its worth. Shall we connect briefly? > We're only onboarding 2 more companies this month for our private infrastructure that'll reach 40K+ of your target buyers every day. Do you think this could help fortrabbit grow quicker? PS: This only works for companies with wide markets that can handle high meeting volume. > I can give you the names and contact info of people on your website before they even fill out a form. Want to uncover who they are? > I hope things are going well. I'm reaching out about potential sales collaboration. As a freelance sales representative focused on leadgen, I have spent the past ten years in corporate and tech environments. After a brief pause I returned as a freelancer, supporting several businesses with their sales efforts. I still have spare capacity and noticed your recent growth; I believe my experience could help maintain that momentum. Who in your team would be the right contact to discuss this further? > I can show you 1K potential buyers in the market for php hosting solutions. I can give you their information so you can contact them immediately. Want to see the data? > I could reveal contact + company names, emails, & phone numbers, + more of the traffic visiting fortrabbit's website before they ever opt in. Just takes 15-mins to get started. Sound interesting? > This is my final email. If clients are inquiring about AI and you're not providing it, someone else surely will. Here's what will happen: Hire another agency to add it (and realize they don't need you anymore) Go with a competitor who includes AI in their proposals Think you're behind the curve. With our whitelabel chatbot solution, you can capture that revenue without the burden of learning a new skillset. The same offer applies: $0 setup on your next project. $0 until you land an upsell. Wanna talk to that AI chatbot live? > Unilever automates recruitment with AI and saves £1 million annually. A 50-person start-up builds a mini AI workflow and cuts 10-15 hours/week from manual tasks. You don't need a massive AI team. You need logic: analyze, automate, optimize. XX helps fortrabbit implement custom AI models, chatbots, and workflow automations that plug right into your current systems. I can share a short case study showing how we delivered similar results—want me to send it? > Noticed you've been helping web developers and startups with PHP hosting. We can queue upto seven enquiries every month for you by spotting web development agencies that frequently post new project listings. Those agency owners tend to respond fast when the topic is hosting solutions. I can show you how we're finding these leads and what's getting replies if helpful. > I hope you're doing well. Just wanted to follow up in case my last note got buried. I'd really appreciate the opportunity to have a quick call with you. Would you be open to a brief meeting this week or next or when you have time? Please share your availability. > I'm writing to ask permission to close your file for now. I haven't heard back, so I assume improving trial-to-paid conversions isn't the main priority for fortrabbit right now. I won't follow up again. If you ever decide you want to automate failed payment recovery, feel free to ping me. Best of luck with the managed cloud hosting platform for php web developers and agencies growth! > As I recall, Fortrabbit are actively seeking Cloud Management Software buyers, is this still the case? If so, we have around 5,000 individuals looking to purchase these services every month. I would love to give you a chance to test a 3 month, discounted pilot campaign. Should I send options to you or is there someone else I should be speaking to? > Quick nudge. We track online research activity and pull out the only those showing strong intent for solutions your company provides in the Computer Networking space. Each one comes with verified contacts mapped to the account and recent activity like last-seen date, so your team starts with the people most likely to say yes. Reply with your best customer type, and I'll send a small sample. Should I? > checked fortrabbit.com/llms.txt and got a 404. That file tells AI crawlers how to read your site. Without it, ChatGPT and Perplexity are guessing what Fortrabbit does - and usually guessing wrong (or ignoring you entirely).We make your site visible to AI - and get you cited in 90 days. Mind if we build your llms.txt for free? Just reply "yes" and we'll get started. > I hope you're doing well. I'm reaching out with a unique opportunity to collaborate on something impactful. As a professional financial broker with one of the leading loan funding firms, I work with businesses and individuals to secure funding at highly competitive rates, helping turn ideas into thriving ventures. We're also offering a 0.5% commission to partners who refer project owners or businesses in need of funding. Whether you're in finance, real estate, consulting, or simply well-connected, this could be a mutually rewarding partnership. If this resonates with you, or if you know someone who could benefit, please feel free to contact me for more details and next steps. Let's build something valuable together. > Seriously, we provision infinite Microsoft Azure inboxes on a private infrastructure at no charge. Integrates with any sending tools. You can land more appointments and increase your sending volume for cold email without paying per inbox. Companies like XXX.ai, XXX.ai, XXX.ai, XXX.ai love our product to spin up cold email infra with high deliverability. Would 10 domains at no charge help you give it a try? (500 emails/day). No worries — this is my final message. > Hope this finds you well, and with a decent cup of coffee nearby. I was planning to share a quick example of how teams like fortrabbit are using AI/ML to cut manual work and simplify everyday workflows. Would it be okay if I shared the details? > We design and redesign websites, and I drafted a clear clean layout for Fortrabbit; can I send it for your review and if it works for you we can keep going? > We are a Bangladesh-based Co, and we provide services across the Globe. We provide both Business and Consumer contacts inclusive of verified contact numbers and emails for your marketing initiatives. Would you be interested in receiving a few examples from our updated dataset? Kindly let me know your Target Audience/Target Geography, so that we can provide complete details with a few samples. > Just checking in to see if you've had a chance to review my earlier message. I genuinely think this partnership could add great value for both our readers. Would you be open to a short discussion this week? > I just generated a custom Ai assistant for Fortrabbit using your existing support docs. It automatically handles repetitive Tier 1 tickets, freeing up your human agents. Want to give it a spin? > I came across fortrabbit while looking into fast-growing hosting providers, and really liked what you're building. We work with teams like yours to handle growing technical workloads through fully managed, white-labeled backend operations (L1-L3). Our engineers help improve response times, reduce ticket queues, and ensure consistent service delivery, without growing your in-house team. Would it make sense to explore if this could complement your current setup? > Every week an AI engineering role stays open is a week of lost innovation and potential revenue for your company. We specialize in closing these "impossible" roles in under 30 days by leveraging a private network of passive candidates. We recently helped a gaming studio implement real-time generative assets by finding them the perfect specialist. Is there a role on your team that has been open for more than 60 days? > Circling back on my note about connecting you with active Wix, Squarespace, and WordPress users. I'd love to explore how we can help you strategically reach and convert this audience based on your specific niche and goals. Since you're one of the notable players in the Website Builder tech market, would you like to expand your customer-base by reaching out to your competitors' active customers with your offerings? Here are some suggestions: Squarespace, Wix, WordPress. Let me know if any of the above aligns with your targeting strategy and I'd love to tailor the numbers based on your niche. > Briefly touched on Fortrabbit during a discussion we were having with the Price Org last week in Chicago. Thought we might have overlapping interests in what we see in the industry. Can we connect next week if you have a sec? > We have came up with a different strategy for smaller saas teams, interested in your feedback as you're exactly who we built this for. I'll run fortrabbit's paid ads for as long as you want, on whichever platform you choose (one platform or several) after one small and flat payment. Without retainers or revenue cuts, What do you think? > Noticed you've been helping web developers and startups with PHP hosting. We can queue upto nine enquiries every month for you by spotting web development agencies that frequently post new project listings. Those agency owners tend to respond fast when the topic is hosting solutions. Interested? > could I give Fortrabbit a free ad creative designed to book demos with professional web developers, freelancers, agencies, startups? P.S. We've added over $38M ARR for 35+ B2B SaaS clients with our creatives - including Instantly AI, ListKit, and Trustworthy. > Let's be real... your inbox is probably full of "game-changing" tech pitches. I wanted to share a straightforward idea on how teams like fortrabbit are using AI and machine learning to automate workflows, surface actionable insights, and drive measurable efficiency gains without unnecessary complexity. Want me to send a case study your way, or should we grab a coffee-friendly slot to talk through how this could work for fortrabbit? > We understand that Fortrabbit offers marketing and promotion services, and we would love to collaborate by providing our payment solutions. Integrating our services will give your clients access to fast, secure, and cost-effective transactions, along with additional opportunities that may benefit your business. With the rise of global digital transactions, offering crypto as a payment option isn't just about innovation, it's about staying ahead of the curve. Our platform makes it simple, secure, and economical for businesses to do exactly that. > Just checking in on my last email, we partner with XXXX University to operate a dedicated R&D center with a focus on applied AI and LLM technologies. This collaboration enables us to merge academic research with hands-on engineering, turning AI innovations into production-ready systems. Furthermore, XXXX is an NVIDIA Ambassador, providing us with early access to modern GPU-based AI architectures and best practices. Building upon this base, we have built strong capabilities across Full-Stack software development, AI/ML, and Data Engineering, providing support for sophisticated and data-rich projects for our European clients. I'd like to share our rate card and company profile for your perusal, if you're open to it? > For context - we're averaging a sub $200 cost per demo, 3.84x ROAS and 7 day payback period across our B2B SaaS clients. Open to taking a look at the free ad creative for Fortrabbit? > I'm reaching out to you because I just came from a project with a company similar to Fortrabbit in the e-commerce sector. We often see that AI is already being used, but the potential is hardly being exploited. We offer training courses with a focus on AI that can be funded up to 100% by the government. Over 100 companies have already successfully doubled productivity per employee, automated processes, and reduced costs through our courses. I would like to present the options for Fortrabbit to you. If this is interesting for you, let's have a brief talk in the next few days. > Following up, I realize you might hesitant about taking investor calls. To reiterate, XXX is not a typical PE fund. As the Founder of XXX, backed by the XXX family's $30B+ balance sheet, I invest long-term without pressure to force an exit. We've partnered with founders to accelerate growth while preserving their culture, like when we helped a SaaS company nearly quadruple ARR in a year. Would you have 15 minutes in the next week or two for a quick call? > I'm just following up on my earlier message to see if this could be useful for fortrabbit. We help teams add remote developers, designers, and marketers without a long hiring process. If you like, I can share a few profiles so you can quickly see if it's a fit. Please let me know. > I'm reaching out again to see to see if you'd be open to discussing how XXX can support your development needs. A significant benefit we offer is that our developers are senior and proficient in AI-powered development tools, enabling clients to save at least 30% in development effort while ensuring swifter and more efficient delivery. With a team of 100% in-house senior Software and AI/ML engineers, we provide only top-tier developers (10% of Vietnam) tailored to your needs. We'll be making our way to Europe this year 2026 and would love the opportunity to meet in person to explore potential collaboration. Would you be interested in reviewing our rates, company profiles, or the meetup at your office? > We didn't circle back — and I didn't want to move forward without touching base. We're closing in on locking in the network, and if this is still on your radar, I'd be happy to give you a full rundown of where things are. > My warm investor network is actively looking at deals in your sector this quarter. If you are fundraising for Fortrabbit, I can arrange warm introductions, and you don't pay a penny if we can't get you the intro. > Frank - found a subreddit that would be great for you to advertise to. There's 169K members in r/PHP, and they're already having conversations about cloud hosting. Could I share some ideas for how Fortrabbit could be advertising directly in those conversations? We've found our audience is 27% more likely to make a purchase decision after seeing an ad on Reddit compared to other sites. > Fortrabbit - quick example of results from our ad creatives: We helped a B2B SaaS startup book 128 demos and add $150k in MRR in 62 days running Meta ads (at a 3.91X ROAS). Happy to create a free ad creative for using the same formats. Open to reviewing? > I recently came across your article on blog-frbit.frb.io, and the clarity and insight you bring to complex subjects really impressed me. It's clear your readers trust your expertise. At Bluehost, we've been expanding our educational content around Tech, Web Hosting, Saas, Digital Marketing. Business. Wordpress. E-commerce, and would love to explore collaboration opportunities, whether that's Guest posting or Contextual link collaboration. I believe this could bring real value to both our audiences. Would you be open to discussing it briefly? > Just a quick nudge to see if you've had a moment to glance at my earlier email. Your thoughts would be greatly appreciated. > I came across fortrabbit last week and noticed something: your work for customers is strong, but you are not telling that story on LinkedIn yet. I do not say this as criticism, but because I see an opportunity here. We are currently looking for a company in the computer networking space for which we can deliver our full LinkedIn package: profile optimization, content strategy, targeted follower growth, and data-driven DM outreach. Over 12 weeks, with full transparency. In return, we document the process and results as a case study, in close coordination with you and only with your approval. Would you be open to a short call where I can outline the exact scope? 15 minutes, no obligation. > I won't follow up again after this. But I'd be doing you a disservice if I didn't say - the leads we reach out to on your behalf aren't cold. They will be the leads that are already searching for solutions like yours. We simply position Fortrabbit in front of them before competitors. Last week alone we generated $3000+ in new revenue for XXXX from engaging 3000 high-intent prospects. If you're open, let's find 15 minutes this week - if not, no worries at all. > Sorry for the back-to-back emails here. Just wanted to get this in front of you to see if it's of interest. We kicked off the quarter with a record-breaking February at XXX, and March is shaping up to carry that momentum forward amid shifts we're seeing across the market. If you want to talk through perks, now's the time to do it. If the timing's off - we can certainly reconnect down the line. Let me know what makes the most sense. > I tested Fortrabbit with an AI SEO audit. You got 50/100. Your crucial structured data is absent—buyers searching "best PHP cloud hosting" in ChatGPT will not see you first. We help SaaS companies track AI visibility and fix technical gaps so you show up in AI search. We evaluate your pages, citations, and gaps vs competitor like PHPPayroll. Then publish content that fills the gaps. How about I set up the missing files as a no-charge demo? Then you can tell me whether this fits Fortrabbit. > I'm asking openly: is winning new business currently not a topic for you, or have you already solved that internally? With my best clients, there was the same skepticism at first, until we set up the system properly once. After that, the first conversations with decision-makers came in almost automatically. If you simply don't have capacity right now, that's totally fine, then I'll note you for later. But if you're generally open, I could show you in 5 minutes how this looks for your competitors. A quick "yes" or "no" is enough for me. Then I know how to categorize it. Have a nice Tuesday! # Cloudscapes - Comparing PHP Cloud Hosting Platforms Source: https://blog.fortrabbit.com/comparing-cloud-hosting-platforms Created: 2012-07-09 Author: Frank Lämmer Tags: opinion > A 2012 snapshot of the PHP PaaS field — Heroku, PHP Fog, Pagodabox, dotCloud, cloudControl and the European newcomers. Most of them are gone. We are currently building yet another **have recently launched** a [PHP Cloud Platform](http://fortrabbit.com) ourselves. Of course we looked around to see what the others are up to. This is my (Frank) personal point of view of the current market situation showcasing my favorite services. I try not to judge, neither i will compare features nor prices. ::CallOut{alert} Written in 2012. Most of the platforms below no longer exist under these names. A later look at the same field: [Cloudscapes revisited](/cloudscapes-revisited-php-cloud-overview) from 2014, and [Is PaaS dead?](/cloudscapes-rerevisited) from 2016. For what fortrabbit runs today, see :ContentLink{href="/php-cloud-hosting" text="PHP cloud hosting" prefix="www"}. :: **tl;dr** All services are great, check them out yourself to find the one that matches your needs the most. They all offer a free trial or even a freemium plan. ## The PaaS Category Cloud Hosting is a difficult term, used by many people for entirely different purposes. So let me make clear what I am talking about. First off, I am not speaking about those old school web-hosters, which use this buzz word to market their good ol' Virtual Private Servers as the next big thing. I am talking about something else: new-school, new-approach, new-generation clouds. Big players like Amazon Web Services, Windows Azure, Rackspace, Google App Engine, IBM and Softlayer actually run data centers supplying the infrastructure (IaaS) for most cloud hosting platforms. I see those kinds of platforms as an abstraction layer on top of cloud technology. Sure, you could simply call them "resource resellers", but i do not think that this describes the actual reality. So, in my opinion, what a "real" Cloud Hosting PaaS does is: - Buying a big piece of cloud cake, refine it, slice it into smaller pieces and sell it - this is what you would call a reseller. - Deal with complex technology, built a system on top of it that is easy to use for your client - and this is the service they provide making it worth the money. The core task for a cloud hosting provider is to bring benefit on top of the actual resources to the web developer. In short, those mostly include: - True scalability - without PHD in rocket science to manage it. - An interface (CLI and/or GUI) to control the hosting without certified SysAdmin skills (DevOps). - Easy access to new technologies, such as NoSQL Databases, version controlled deployments and so on. Enough talk, let's see who is there… ## PHP Cloud Platforms in the United States Of course the US market is the biggest and was the first. They always invent such things. ### Heroku The original inventor of this category founded in 2007, now owned by Salesforce. They realized that a cool Ruby hosting platform was missing (but they where wrong about the browser based code editor). One can't run Ruby apps on most of the old school shared hosts. Maybe the hip Ruby developers adapt new technologies a bit quicker. Straight forward: The admin tool is a comand-line interface. Heroku invented an AddOn market place where external providers can offer their services - an App Store for Cloud Hosting services. They actually don't offer PHP, but i've heard that there is hidden support. Heroku is based in San Francisco and relies on AWS. [heroku.com](http://heroku.com) ### PHP Fog / AppFog The idea behind PHP Fog is pretty simple: Heroku is very successful, there are way more PHP developers than Rails guys. So there has to be a market for a PHP Cloud Hosting Platform. Founder Lucas Carlson proved this with PHP Fog. Instead of a CLI like on Heroku PHP Fog features a nice hipster web interface even with one click installers. Currently there is a kind of merge going on, the new product is called AppFog. AppFog is more advanced and more complex and i have to admit that i still don't get what it is really about. This funded startup is based in Portland. PHPfog is hosted on AWS. AppFog supports multiple cloud vendors. [appfog.com](http://appfog.com) ### Pagodabox The new kid on the block. The approach is a bit similar to PHP Fog: it's exclusively made for PHP and it also features a hipster web interface. But apart from that it's pretty unique with some really fresh ideas such as the box file. It's fun to see how this projects grows, it's under very active development. "An Object Oriented Hosting Framework" is a cool claim. Probably the only thing i don't like about Pagodabox is that you they don't tell you anything about their company and the people behind it. Earlier this year they had problems with the underlying cloud infrastructure of Softtlayer, so they switched to physical hardware. [pagodabox.com](http://pagodabox.com) ### dotCloud I have to admit that dotCloud was always a bit under my radar, but they recently ramped up their products. The platform supports offer various programming languages and services as a stack (ruby, PHP, Perl(!), Nodejs and different NoSQL and SQL databases). Unlimited! sandboxes for development are free. They have a Command Line Interface to control the apps and a big documentation with lots of code examples. DotCloud is a funded startup based in San Francisco. [dotcloud.com](https://www.dotcloud.com/) ### ApCera Yet another funded Startup PaaS from the valley, currently without public informations available. I guess they will support PHP as well. Derek Collison, the Founder and CEO is the chief architect of Cloud Foundry (a VMware cloud venture) and is also involved in AppFog. They recently bought in [PaaS.io](http://paas.io) (guess what, yet another Cloud PaaS from the valley) and some other guys. [apcera.com](http://www.apcera.com/) ## PHP Cloud Platforms in Europe From my perspective it makes not much sense to go with an US cloud provider for a project in Europe (unless you expect your vistors to come mostly from the US). It's not only data latency across the ocean (you might use a CDN to back this up), it's also the legal stuff (contracts) and the billing. So where are the cloud platforms for Europe? There are definitely some on the raise. At the time of this writing it looked to me that some currently run something that is more a Minimum Viable Product than a reliable business solution. ### CloudControl For me Cloud Control looks a bit like Heroku (great artists steal). They have a Command Line Interface to control their apps and also an AddOn market place. But it's build for PHP, actually right now they are building support for Ruby and Python. The documentation is well done and extensive. I am not quite sure how to pay there, they don't offer automated billing like direct debit or credit card yet. Cloud Control is a funded startup based in Berlin and hosted on AWS / EU. They got quite some good press in the German tech blog and startup scene. [cloudcontrol.com](http://cloudcontrol.com) ### Relbit “Simplicity of a web hosting, the power of cloud.” is the claim. After i signed up for the free trial i got an auto-responder saying that a “trouble ticket” has been opened - umm. They support PHP primarily, have a web control panel and an PHP SDK(?!). The documentation-wiki is quite ok . Relbit is located in Bratislava (Slovakia) and they offer different data center locations. [relbit.com](http://relbit.com/) ### Omnicloud We have just discovered Omnicloud, they are currently in private BETA and we have not been invited yet. They support PHP now and plan to support Ruby soon. It seems they have a webcontrol panel. Onmicloud comes from Stockholm and is hosted on AWS prices are listed in USD. Currently in private Beta - public launch expected to be in September 2012. [omnicloudapp.com](https://omnicloudapp.com/) ### Stackblaze Also a brand new service. I have tested it out just quickly. Looks promising overall. I could not figure some things (is their any test address? Who to access by Git?) Stackblaze is based in Brighton and runs on servers by OVH (a big French hoster). [stackblaze.com](http://stackblaze.com) ### Clever Cloud I am not sure why they have this big silhouette of a bong on their homepage. _The cloud that get's you high?_ Apart from that this service also looks very interesting. They plan to support multiple languages (Scala, Ruby, PHP, Java). I don't know about their setup and interface. Right now they are collecting e-mails for the private beta. Pretty obviously is that they come from France (Nantes). [clever-cloud.com](http://clever-cloud.com) ### Engine Yard (with Orchestra) Orchestra (Ireland) has been acquired by Engine Yard (US) mid 2011. They provide 3 different plans: Free (for free, but very limited environment), Basic (fixed dedicated resources) and Elastic (auto-scaling). You can deploy your app with Git or SVN. Orchestra, unlike many others, do not run on Apache webserver but rather runs on Nginx. The infrastructure is powered by AWS, but it's not clear if they use data centers in US or Europe.[engineyard.com](http://engineyard.com/) ## Closing Note Think different, missing something? Your opinion is highly welcome! Even further Reading: Posts of [Phil Sturgeon,](http://philsturgeon.co.uk/blog/2012/01/2012-the-year-of-php-cloud-hosting '2012 the year of php cloud hosting') [Adam Stachelek](http://cantina.co/2012/02/17/please-paas-the-apps-a-crash-course-in-platform-as-a-service 'Crash course in platform as a service') and watch [this panel at GigaOM](http://gigaom.com/cloud/vendor-lock-in-and-the-challenge-to-platform-as-a-service/). The last click goes to this Japanese PHP PaaS: [phper.jp](http://phper.jp/). # Composer 2 is about to land on fortrabbit Source: https://blog.fortrabbit.com/composer-2-availability Created: 2020-12-16 Author: Oliver Stark Tags: changelog > Composer 2 lands on fortrabbit and makes git deployments considerably faster. What to expect, and how to fix a build that breaks. As requested, we plan to switch to Composer 2 on **Tuesday, the 15th of December 2020**. This will make the Git deployments with Composer much faster. In general we expect nothing but rainbows and unicorns. ## Troubleshooting In some edge cases, your deployments might break. Here is how you can fix things: ### What fortrabbit changed in March 2020 to keep client sites online: remote work, shared responsibility and extended documentation. ## What we are doing We are doing our best to keep the services up and running. We always do that. ### Some of our extra precaution measures - Working remotely since 16th of March - Shared responsibility across the team with workshops and extended documentation - Slowed down interviewing new candidates (hiring) - Reviewed and trained internal standard procedures and emergency plans - Postponed some new releases, like PHP 7.4 and MySQL 8, to focus on stability measures first - Slowed down and skipped some sprint goals to give everyone the time to adapt to the new situation - work as much as it feels good to you ### Slower as usual support response times You might have noticed we respond a bit slower as usual in support. That's because of a general business slow down and the special circumstances we are all facing. Thanks for your understanding and patience. Please make sure to provide all details to your question right away. ### Our business situation The fortrabbit company is a small team of only five. fortrabbit as a business is bootstrapped and profitable. Our situation is good and stable. We will be able to deal with a financial backlash, if there will be one for us. ### Platform stability Remember that the fortrabbit platform is mostly a middleware. The infrastructure itself is running on AWS. We consider this very safe. The fortrabbit service is mostly self-service and highly automated - designed for little human interaction from us. Everyone in the team is replaceable, since critical tasks are defined and documented. We are prepared to keep the platform operational with limited resources.

What you can do

We know that you are going to be creative about the situation. You always are. ### Plan ahead for financially difficult times We have a lot of freelancers and small agencies on board. And we are hosting many websites for small local businesses like restaurants, barber shops, co-working spaces, repair shops, you name it. The regulations required to slow down the spread of the virus might hurt your business, getting you in some financial trouble. If so, get your spendings down. Review your costs here. We have created a new dedicated help article guiding you: - [How to reduce your cloud hosting costs here](https://help.fortrabbit.com/reducing-hosting-costs). There is also a new article explaining [how you can download an App](https://help.fortrabbit.com/downloading-an-app) before deleting it, so that you have fresh local backup. We have also made our [bounce delete rules](https://help.fortrabbit.com/billing/#toc-service-cancellation-after-bounced-payments) public now. This ruleset defines at what point we will have to delete your Apps when invoices get not get processed. We believe it's alaready a fair way to deal with things giving you enough time to react. #### How to contact us to apply for a Covid-19 discount Please contact us upfront, if the crisis will affect your business and you might will have trouble paying our invoices. We will try to arrange something for you. We will look at this on a per case basis to find individual solutions. Please give us all the details we need to understand your situation. Tell us about your business, the current situation and the outlook. Make sure you have taken all steps covered above to reduce your hosting costs already. Please write at least 600 chars outlining your case, so that we can make fact based decisions. #### What to expect We can give you a total discount on your next invoices. This can be up to 40% of your total bill, depending on your case. Please understand that this below our operating costs. The discount can be granted for up to three months. You can apply for extension within the time frame. We are ready to do this for a number of clients, but a discount can not be guaranteed for everyone. Please act responsible. ### Get an emergency contact in place Our [collaboration](https://help.fortrabbit.com/collaboration) features enable you to invite other people to your Company. You might invite a backup person as an Owner, so hir can easily take over operations in case something happens to you. ### Stay healthy and positive We wish you all the best. Thanks for being around and the trust in our services. You are awesome. We already see a lot of creativity here, adapting to the new situation. Take care. Best wishes from Berlin. # Craft CMS CVE-2023-41892 Source: https://blog.fortrabbit.com/craft-cms-cve-2023-41892 Created: 2024-02-29 Author: Frank Lämmer Tags: webdev > Update your Craft CMS 4 installation. There is a low-effort high-impact vulnerability out there. ## Affected Craft CMS versions - `>= 4.0.0-RC1` - `<= 4.4.14` ## Actions we have been taking As your friendly Craft CMS web-hosting service, we have identified affected Apps by automatically scanning the deployed `composer.json` file and informed attached Accounts about the vulnerability by email. ## Actions to be done by you Dear web master, update your public Craft CMS 4 installation to at least version 4.4.15. The higher the better. The most current version as of this writing is 4.8. We recommend to update your local installation in your web development environment first and then deploy the latest version. [Here is a guide](https://help.fortrabbit.com/craft-update) how to best do that. In addition, as recommended, best reset all passwords of your Craft CMS users, refresh the security key, reset the database password, reset all private details or secrets that might have been leaked. ## Links - - ## Related Craft CMS reading - [Craft CMS CVE 2025-32432](/craft-cms-cve-2025-32432) — more recent high-impact vulnerability. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — staying on a current version is the best mitigation. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — general tuning and hardening for Craft installs. --- - [Craft CMS guides](/guides/craft-cms) # Craft CMS CVE 2025-32432 Source: https://blog.fortrabbit.com/craft-cms-cve-2025-32432 Created: 2025-05-07 09:24:51 Author: Frank Lämmer Tags: webdev > A high-impact Craft CMS vulnerability in the asset transform endpoint, what fortrabbit blocked, and what every installation must update. ## Actions we have been taking Since May 6th, we are blocking requests to the affected `actions/assets/generate-transform` endpoint. This should stop all further hacking attempts. We have seen a wave of attacks coming in from 2nd of May on. ## Impact fortrabbit Apps are running in isolated, jailed containers. Which means that one affected App will not harm other Apps. Our enhanced security also means that certain abuse patterns like cryptomining are not possible. But like with any web hosting, once malicious actors gain access, they control your website. ## Actions required by you Please mind that you are responsible for the code you write and bring to the fortrabbit platform. Updating CraftCMS might not be enough if the website is already affected, you might also have to clean out malicious files. ### Update your Craft CMS installation Upgrade your Craft CMS installation to the latest version. We recommend to first update your local installation in your web development environment and then deploy the latest version. If you can not upgrade, because of dependencies conflicts, install the security patch (see links below). ### Fixed Craft CMS versions Craft CMS released fixes on April 11th 2025. If you haven't updated your installation, it's vulnerable. These versions are fixed, anything below is affected: - 3.9.15 - 4.14.15 - 5.6.17 ### Check if your Apps are affected These things can indicate your website has been hacked. - Spikes in requests and errors, check the metrics - Database: additional admin users have been added - Obfuscated code in `index.php` and other files - Changed `.htaccess` file - Suspicious files/code not part of the repo (some examples below) ```raw .well-known/* .widgets.php accesson.php autoload_classmap.php cgi-bin/* CoreCheck.php craftt-api.php envcraft.php m.php memberfuns.php mn.php mnb.php wp-blogs.php ``` Some files might be deeply hidden with existing folder structure like so: ```raw assets/_120x78_crop_center-center_none/-vwugcm.php assets/_240x122_crop_center-center_none/-gqpmnb.php assets/_68x56_crop_center-center_none/-yuobgf.php cpresources/4c4d6e37/d3-format/-rfihgs.php cpresources/718fe862/mode/cypher/-nswipf.php cpresources/718fe862/mode/swift/-oxtkip.php cpresources/926d5982/js/captchas/-wtfbav.php cpresources/d87ff9ec/-npcqfu.php migrations/... templates/... vendor/... ``` It's a also possible that existing files contain malicious code or have been replaced. Don't trust the file modification dates. ### Clean your installations If your website has been affected, it is crucial to remove all potential back doors. You can use our backups to restore to an earlier state. If your plan includes backups, see if you have access to a version that is not affected. Use your local environment to update or patch that version and then deploy/upload its contents. Additionally, take the following steps to secure your installation: - Reset all Craft CMS user passwords - Refresh the security key - Reset the database password - Update and secure any private details or secrets that may have been exposed (e.g., third-party API credentials) Pro Apps have ephemeral storage. Next time you deploy ay added code will be gone. Still consider credentials to be leaked and check the database. ## Links - [Craft CMS: CVE-2025‑32432](https://craftcms.com/knowledge-base/craft-cms-cve-2025-32432) - [Orange Cyberdefence: Investigating an in-the-wild campaign using RCE in CraftCMS](https://sensepost.com/blog/2025/investigating-an-in-the-wild-campaign-using-rce-in-craftcms/) ## Related Craft CMS reading - [Craft CMS CVE-2023-41892](/craft-cms-cve-2023-41892) — earlier vulnerability worth checking too. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — staying on a current version is the best mitigation. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — general tuning and hardening for Craft installs. --- - [Craft CMS guides](/guides/craft-cms) # Frontend testing for Craft CMS Source: https://blog.fortrabbit.com/craft-cms-frontend-testing-with-codeception-and-cypress Created: 2022-09-21 Author: Piotr Pogorzelski Tags: webdev > Frontend testing for a Craft CMS site with Codeception and Cypress: what to cover, how to set the suites up, and what the tests catch. ## Why test Craft CMS websites? Software testing is one of the most important tools in the hands of software developers - it allows us to quickly make modifications in the code, without worrying that some unexpected bugs will be discovered later on. Contrary to common belief, tests are not the domain of complicated applications - in this article, we will show you how you can test Craft CMS templates using Codeception and Cypress. But why would you need to test Craft CMS templates, even if your website does not have any custom modules or plugin code? As Twig components grow more complicated and are reused in multiple parts of the site, a single change can lead to unforeseen results appearing in other parts of the site. A testing script could visit multiple part of the website, check if a specific piece of content is rendering correctly, and perform common user actions like logging in, sending forms or, if we're talking about a commerce site, adding products to the shopping cart and creating orders. These kinds of tests are usually performed manually by humans, by "clicking-through" the website - but doing that is kinda tedious and there is usually not enough time to test everything manually as often as it should be done. So when we finally find errors in the website, it can be hard to find out what specific change introduced them. ## Takeaways from this article Here, we will describe and compare two different frameworks for testing Craft CMS websites: - [Cypress](https://www.cypress.io/) - E2E tests - [Codeception](https://codeception.com/docs/03-AcceptanceTests) - acceptance testing What are acceptance tests and E2E tests? To be honest, these terms are bit murky, and depending who you ask, you might get slightly different answers. - E2E (end to end) tests are tests performed under real-life scenarios - they test the application as a whole, instead of its isolated components - Acceptance tests are tests of the application which determine if it meets required specifications - and will be "accepted" by its users In practice, both Codeception acceptance tests and Cypress E2E tests will do one and the same - render a website, interact with it and check if the expected result occurs. ## Spoke & Chain demo site To show how tests work in practice, [we created a fork](https://github.com/piotrpog/spoke-and-chain-testing) of the official Craft Commerce demo site, Spoke & Chain. This site already has Cypress tests included - we added some new ones, as well as Codeception tests, so these two frameworks can be compared using the working examples. In this article we will describe: - Testing a simple search form - Testing if multiple pages render correctly and without errors - Testing the Craft Commerce checkout process 'Spoke & Chain' uses Nitro and DDEV configuration, but if you don't want to use it, you can just set up the website the regular way, by installing composer packages and providing database connection data in the `.env` file. Remember to use `seed.sql` provided in the repository as your database, so your tests have proper content to use. ## Cypress E2E tests Cypress is a JavaScript-based testing framework that allows us to run E2E tests. It runs its tests in a web browser, which lets us watch them execute in real-time. Cypress is a commercial offering with monthly pricing starting at $75 at the time of writing. There is also a limited free tier sufficient for basic tasks. Cypress 10 used in Spoke & Chain E2E tests is supported by Node versions 12 to 16. To install Cypress, just run `npm install` in the console - the Cypress package is included in the `package.json` file. Along with it, the project also includes packages responsible for compiling framework assets, although compiled CSS and JS files are already present in the project. One of the packages, `webapp-webpack-plugin` is compatible only with Node 12 - if you want to install the project using a newer version of Node, you need to remove this package from `package.json` before installation. Doing so won't stop you from using Cypress tests in any way. Before you run Cypress, you need to create a `cypress.config.js` file which will provide configuration and environment variables for our tests. The repository contains `cypress.config.example.js` which we can rename to `cypress.config.js`. There we can set a base website URL depending on our server setup or control panel login and password. Craft admin logins are stored in `cypress.config.js`, you can use the `php craft users/create --admin` console command to create a new admin user. Spoke & Chain uses a header menu fixed to the top of the page. This could potentially cause problems with tests, because when Cypress scrolls to an element it wants to interact with, by default it scrolls just far enough for the element to appear on top of the viewport - so this element would get covered by the fixed menu and Cypress would throw an error. This can be avoided by passing `{scrollBehavior: 'center'}` setting to methods like `click()`; however not every Cypress method accepts this setting - for example the `select()` method used for interacting with ` {% if query is not empty %} Results for {{query}}:
{% for item in searchResults %} {{item.title}}
{% endfor %} {% endif %} ``` And here's our test: ```js it('search form should work correctly', function () { cy.visit('/search-test'); cy.get('#searchText').type('Welcome'); cy.get('#submit').click(); cy.get('.result-link').contains('Welcome Courtney Duncan'); cy.get('.result-link').contains('Adventure Journal on the Pine Mountain 2').should('not.exist'); }); ``` As you can see, Cypress uses methods that simulate interaction with the website. [`visit`](https://docs.cypress.io/api/commands/visit) is used to go to the search form URL (same as the search form filename - thanks to Craft CMS routing), [`type`](https://docs.cypress.io/api/commands/type) simulates typing into an input, and [`click`](https://docs.cypress.io/api/commands/click) simulates clicking an element. We also use the [`get`](https://docs.cypress.io/api/commands/get) method to select specific DOM elements using a CSS selector - just like it works with regular `document.querySelector()` or jQuery. Keep in mind that this requires your element to have unique HTML attributes - so if you use a CSS framework like Tailwind that allow you to style the page using universal CSS classes, you still need to attach some unique class, ID or data attribute to elements used in tests. Finally, we make the most basic assertion using [`contains`](https://docs.cypress.io/api/commands/contains) to check for the existence of content on the rendered website. That way we determine if test was succesful or not. Cypress supports all kinds of [Assertions](https://docs.cypress.io/guides/references/assertions); documenting them here would go beyond the scope of the article. ### Cypress - checking multiple pages for HTTP errors The most basic form of testing a site is by visiting various pages and checking that nothing broke. It might seem that just manually opening the homepage in a browser would be quicker then setting up these tests. But if we need to test 50 pages (for example if we modified some website component that is used globally), using automated testing begins to show its usefulness. Our test is located in the `cypress/e2e/new/checkPages.cy.js` file: ```js const urls = ['/', '/bikes', '/services', '/articles', '/contact']; urls.forEach((url) => { it('should render correctly', function () { cy.visit(url); }); }); ``` As you can see, all we do is loop through URIs and use the `visit` method to request them. But where is the assertion? Well, Cypress will mark a test as failed if the response code of the visited page is anything other than 2xx or 3xx - for example a 500 internal server error or a 404 not found. ### Cypress - testing the checkout process Now it's time for something more complicated: testing the e-commerce checkout process. Contrary to the two basic tests we described before, this one is included with Spoke & Chain demo site by default: you can find it here: `cypress\e2e\front\checkout.cy.js`. First, let's take a look at the start of the file. Here, we set up a loop which will run tests for every screen size defined in the `viewport-sizes` file. We also load the user information fixture from the [cypress/fixtures/user.json](https://github.com/craftcms/spoke-and-chain/blob/stable/cypress/fixtures/user.json) file and assign it to the `user` variable so we have some data to use in our tests. Using `it` we define the name of our test. ```js const sizes = require('../../viewport-sizes') sizes.forEach((size) => { describe(`Checkout on ${size} screen`, () => { beforeEach(() => { cy.setViewportSize(size) // Define the user fixture cy.fixture('user').as('user') }) it('should add a product to the cart and checkout as guest', function () { ``` Next, our test performs actions which we would do if we tested the checkout manually - visiting URLs, clicking buttons, and typing into forms. This test visits multiple stages of the checkout process, but we don't need to specify their URLs - just submitting forms will redirect us to the proper pages. Note how we use `this.user.email` and other variables with the `type` method - it's the data taken from the fixture. ```js // Add a product to the cart cy.visit('/product/san-quentin-24'); cy.get('#buy button[type=submit]').click(); // Navigate to the cart cy.get('button.cart-toggle').click(); cy.get('div.cart-menu a.button.submit').contains('Check Out').click(); // Checkout as guest cy.get('#guest-checkout button[type=submit]').contains('Continue as Guest'); cy.get('#guest-checkout input[type=text]').type(this.user.email); cy.get('#guest-checkout button[type=submit]').click(); // Shipping address cy.get('form#checkout-address input[name="shippingAddress[firstName]"]').type(this.user.address.firstName); cy.get('form#checkout-address input[name="shippingAddress[lastName]"]').type(this.user.address.lastName); cy.get('form#checkout-address input[name="shippingAddress[addressLine1]"]').type(this.user.address.addressLine1); cy.get('form#checkout-address input[name="shippingAddress[locality]"]').type(this.user.address.locality); cy.get('form#checkout-address input[name="shippingAddress[postalCode]"]').type(this.user.address.postalCode); cy.get('form#checkout-address select[name="shippingAddress[countryCode]"]').select(this.user.address.countryCode); cy.get('form#checkout-address button[type=submit]').click(); // Use the default shipping method cy.get('form#checkout-shipping-method input[type=radio][value="freeShipping"]').click(); cy.get('form#checkout-shipping-method button[type=submit]').click(); // Fill credit card details and pay cy.get('form#checkout-payment input[name="paymentForm[dummy][firstName]"]').type(this.user.card.firstName); cy.get('form#checkout-payment input[name="paymentForm[dummy][lastName]"]').type(this.user.card.lastName); cy.get('form#checkout-payment input[name="paymentForm[dummy][number]"]').type(this.user.card.number); cy.get('form#checkout-payment input[name="paymentForm[dummy][expiry]"]').type(this.user.card.expiry); cy.get('form#checkout-payment input[name="paymentForm[dummy][cvv]"]').type(this.user.card.cvv); cy.get('form#checkout-payment button[type=submit]').click(); ``` Finally, we just check if the page we end up on after submitting the checkout form displays a success message, using the `contains` method. ```js cy.get('h1').contains('Success'); ``` ## Codeception acceptance testing Codeception is a standard PHP testing framework that has a Craft CMS integration. It is most commonly used for unit testing Craft plugins. We can also set it up for testing the website's frontend with acceptance tests. Codeception is free to use without limits. Enterprise support is available. By default, Codeception acceptance tests are run in headless mode using the `PhpBrowser`. Under the hood it uses Guzzle and Symfony BrowserKit to perform HTTP requests and to parse HTML. If you rely on JavaScript execution during your tests use the `WebDriver`. The long version, including pro and cons, and a setup guide is documented [here](https://codeception.com/docs/AcceptanceTests). One advantage that Codeception has over Cypress is that it is much more tightly coupled with Craft CMS. For Cypress, only HTML code matters. With Codeception, we can are in control of the CMS data for our tests. We can assure that our main database will not be flooded with test-related data by using a different database. Fixtures ([see the Craft CMS docs](https://craftcms.com/docs/4.x/testing/testing-craft/fixtures.html)) allow us to create a predictable dataset for different test scenarios. Please bear in mind, fixtures in Codeception are very different than the ones in Cypress. The Craft CMS documentation has [instructions](https://craftcms.com/docs/4.x/testing/testing-craft/setup.html) for setting up Codeception tests. Using them, we added Codeception to the Spoke & Chain project - with just a few modifications. - We changed the `dbSetup` setting in `codeception.yml` so that the database is not reset each time a single test runs. Although Codeception acceptance tests do not reset the database (only unit tests do), we still felt it's better to disable this feature to prevent any accidental data loss. - We added an `output` setting to `codeception.yml` - there you can find the HTML output of failed acceptance tests. - We installed additional composer packages `codeception/module-phpbrowser` and `codeception/module-yii2` used in our tests. - We added proper configuration to the `tests/acceptance.suite.yml` file for our acceptance tests, and generated an `AcceptanceTester` class using the `./vendor/bin/codecept build` command. Note that our `codeception.yml` config file uses a environment variable containing the website base URL `PRIMARY_SITE_URL` - taken from the `tests/.env` file. ```yml actor: AcceptanceTester modules: enabled: - PhpBrowser: url: '%PRIMARY_SITE_URL%' ``` Codeception tests use their own `.env` file, but if you want them to use the same database as the regular site, you can just copy the `.env` file into the `tests` directory. To run acceptance tests, use the command `./vendor/bin/codecept run acceptance`. You can also run specific tests with `./vendor/bin/codecept run acceptance testClass`, where `testClass` represents a specific test class. Now, let's recreate all the previously described Cypress tests in Codeception. ### Simple Codeception example - search form Just as with the Cypress tests, Codeception acceptance tests have methods for interacting with the website - we can click buttons, submit forms and check for the contents of rendered HTML elements. This can be used to check if forms such as the search form work correctly. Here's the `tests/acceptance/SearchFormCest.php` file. Note that every testing class name needs to end with "Cest". ```php amOnPage('/search-test'); $I->fillField('#searchText', 'Welcome'); $I->click('#submit'); $I->see('Welcome Courtney Duncan', '.result-link'); $I->dontSee('Adventure Journal on the Pine Mountain 2', '.result-link'); } } ``` Unlike with Cypress, here we don't use a separate `get` method for grabbing DOM elements, but just pass element selectors as second parameter. The [click](https://codeception.com/docs/03-AcceptanceTests#click) method tries to locate an element by its text, name, CSS or XPath. ### Codeception - checking multiple pages for errors Now, let's perform our "visiting various pages and checking if nothing broke" test. Here's the test class which will visit the homepage (the page with a `/` URI) and check if any errors show up. If something goes wrong, we will get a response code other than `200` - for example `500` or maybe `404`, which will make test fail due to the `seeResponseCodeIs(200)` assertion. ```php amOnPage('/'); $I->seeResponseCodeIs(200); } } ``` ![](/images/codeception-screenshot.png) Shouldn't we test more than one page though? So, how do we test multiple pages - do we set up separate method for each one? That would lead to tons of code duplication, so we will use [data provider annottions](https://codeception.com/docs/07-AdvancedUsage#DataProvider-Annotations) instead. Here's the final version of our test class, located in the `tests/acceptance/CheckPagesCest.php` file. ```php amOnPage($singleUrl['url']); $I->seeResponseCodeIs(200); } protected function urlsProvider() { return [ ['url' => '/'], ['url' => '/bikes'], ['url' => '/services'], ['url' => '/articles'], ['url' => '/contact'], ]; } } ``` Data from the `urlsProvider` method will be used to dynamically generate multiple tests, using the `rendersCorrectly` method as a template. Note the annotation in the phpdoc block to attach a data testing method. So if you have the habit of removing code comments, your test might stop working. ### Codeception - testing the checkout process Here's the Spoke & Chain checkout test recreated in Codeception - located in the `tests/acceptance/CheckoutCest.php` file. Instead of using Codeception fixtures (which are most often used in unit tests), we used data provider annotation to store example buyer data. Please note the `submitForm` method - it takes an array of form values, where the array key is the input's `name` attribute. This slightly simplifies our test compared to the Cypress one. Other than that - this test works exactly the same as the Cypress version, except it does not check the website in multiple screen resolutions. ```php amOnPage('product/san-quentin-24'); $I->click('#buy button[type=submit]'); // Navigate to the cart $I->click('button.cart-toggle'); $I->see('Check Out', 'div.cart-menu a.button.submit'); $I->click('div.cart-menu a.button.submit'); // Checkout as guest $I->see('Continue as Guest', '#guest-checkout button[type=submit]'); $I->fillField('#guest-checkout input[type=text]', $singleUser['email']); $I->click('#guest-checkout button[type=submit]'); $I->submitForm('form#checkout-address', array('shippingAddress' => array( 'firstName' => $singleUser['firstName'], 'lastName' => $singleUser['lastName'], 'addressLine1' => $singleUser['addressLine1'], 'locality' => $singleUser['locality'], 'postalCode' => $singleUser['postalCode'], 'countryCode' => $singleUser['countryCode'], ))); $I->amOnPage('/checkout/shipping'); // Use the default shipping method $I->click('form#checkout-shipping-method input[type=radio][value="freeShipping"]'); $I->click('form#checkout-shipping-method button[type=submit]'); // Fill credit card details and pay $I->submitForm('form#checkout-payment', array('paymentForm' => array( 'dummy' => array( 'firstName' => $singleUser['firstName'], 'lastName' => $singleUser['lastName'], 'number' => $singleUser['cardNumber'], 'expiry' => $singleUser['cardExpiry'], 'cvv' => $singleUser['cardCvv'], ) ))); // success $I->see('Success', 'h1'); } protected function userProvider() { return [ [ 'email' => 'ben@craftcms.com', 'firstName' => 'Ben', 'lastName' => 'David', 'addressLine1' => '13 rue des Papillons', 'locality' => 'Grenoble', 'postalCode' => '38000', 'countryCode' => 'FR', 'cardNumber' => '4242424242424242', 'cardExpiry' => '03/2026', 'cardCvv' => '123', ], ]; } } ``` ## Summary Both Cypress and Codeception have their pros and cons. There is also the matter of which language you are more comfortable with - PHP or JS. Ultimately, it's up to you which one to choose: - Codeception is tightly coupled with Craft CMS, allows setting up a separate database for testing, is quick and works well in text environments. However by default it does not run JS scripts, which prevents it from testing the Craft CMS control panel. - Cypress is more frontend-oriented, allows running tests in the browser by default and testing multiple breakpoints of a website. While tests run, you can also observe them and pick up any CSS bugs which would not be automatically detected. We hope our article gets you on board with frontend testing and that you will make testing part of your regular development process. As we demonstrated, it is nothing to be afraid of - it can be easily set up and save you time in daily developer work. So go ahead, clone our [Spoke & Chain fork](https://github.com/piotrpog/spoke-and-chain-testing) and see how it works in practice. ## Related Craft CMS reading - [Testing Craft CMS sites with Pest](/craft-cms-pestphp-testing) — unit-level testing alternative. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — performance tuning across the stack. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — tests are your safety net during a major upgrade. _This article is [cross-published at the website of the author](https://craftsnippets.com/articles/frontend-testing-for-craft-cms-websites-with-codeception-and-cypress)._ --- - [Craft CMS guides](/guides/craft-cms) # Testing Craft CMS sites with Pest Source: https://blog.fortrabbit.com/craft-cms-pestphp-testing Created: 2022-12-01 Author: Oliver Stark Tags: webdev > Testing Craft CMS sites with Pest, from the first assertion to a suite that runs on every deploy — for developers who never wrote a test. ## Testing is hard until you practice it You may think writing automated tests is complex and not worth the effort. That's usually the main argument against it. However, even if you've never written a test, you did testing in a way. You did it manually using browser over and over again. You set some expectation in your mind and iterated until you reach the defined goal or acceptance criteria. Your manual testing practice is the answer to the first question: What should I test? The next question you'll come across is: Which tool should I use and how to set it up? To be honest, getting started ain't easy. In Craft the barrier for getting into testing is quite high. So far there is no test tool that integrates with Craft properly and lets you get started in a few minutes. There is some documentation for Codeception, the default test framework for Yii, but it feels like nobody is using it. The adoption of modern frontend testing tools like Cypress or Playwright is probably a bit higher, but those are very generic by nature and do not fully integrate with Craft. We compared both in the [previous blog post](/craft-cms-frontend-testing-with-codeception-and-cypress). ## Why Pest? ![](/images/craft-pest-poster.png) Pest is not reinventing the wheel. It is a layer on top of PHPUnit, the de facto standard tool for testing in PHP. The syntax and the philosophy are inspired by Jest, a popular testing framework in the JavaScript world. [Nuno Maduro](https://github.com/nunomaduro) created it for PHP as he liked writing tests in Jest. Within the last months it became increasingly popular in the Laravel community, hopefully soon in the Craft space too. Pest doesn't work out-of-the-box with Craft. [Mark Huot](https://github.com/markhuot) put a lot of effort into a plugin that takes care of bootstrapping Pest, so you don't have to. The plugin also adds additional functionality which is needed to fully test Craft sites properly. Its main focus is on HTTP tests, which means stuff you previously did manually in the browser becomes an automated test, by using a syntax that is easy to write and read. Although Craft Pest isn't released yet, there is a lot of documentation on [craft-pest.com](https://www.craft-pest.com) already. The docs are not complete, but you can find useful examples to get started quickly. ## How to set up Pest for Craft? It's easy, they said - and it is: ``` # Require the plugin using composer composer require markhuot/craft-pest --dev ``` ``` # Enable the plugin php craft plugin/install pest ``` The install command registers the plugin and creates three files: - `phpunit.xml` The PHPUnit config you rarely need to touch - `tests/Pest.php` Here you can define functions you may want to use in your tests - `tests/ExampleTest.php` A very basic HTTP test on the `/` route (you can remove it later) ## Write your first test In contrast to PHPUnit or Codeception, tests are not defined in PHP classes. All you need is a PHP file in the `/tests` folder. If it becomes crowded create your own structure using subfolders. ```php get('/')->assertOk(); }); it ('loads the contact form', function() { $this->get('/contact')->assertOk(); }); ``` ## Testing Forms The following test is very straight forward, but it introduces some new things we need to break down. ```php get('/search') ->form('#search-form') ->fill('q', 'Pine Mountain') ->submit() ->assertRedirect() ->followRedirect(); // Result: count items $response ->querySelector('.article-card') ->assertCount(2); // Result: assert text $articleCards = $response->querySelector('.article-card'); expect($articleCards->getText()) ->each() ->toContain('Pine Mountain'); }); ``` Explanation: First we visit the `/search` route and assume there is a `
` element. Inside this form there is an `` which we fill with a search string. Then we submit the form, expect a redirect response and follow it. All of these steps must be successful to get the test passing. The previous `followRedirect()` creates a new request and returns a new response we can work with. The `querySelector()` method allows us to narrow down the HTML of the response body. In this example we select DOM elements that match `.article-card` and assert two of them exist. Using Pest's Expectation API you express your expectation in a more human-readable way. This is what we do in the last step, it reads like this: ```php expect(something_given)->toBe/toContain(expectation); ``` ## There is more ### Datasets Datasets in Pest, also known as data providers in PHPUnit, allow you to run certain tests with different data. This is where automated testing really shines. For example, instead of testing a search form with only one static search term `Pine Mountain`, you define an array of terms but keep your actual test simple. More: ### Factories Testing against a consistent dataset is important, this you can achieve by importing a sql dump or by using fixtures. Often more a bit more flexibility is required, and here is where factories come into play. If you have some experience with Laravel, you will notice what this implementation was inspired by. With factories, you actually fill the database with entries and fields for a specific scenario you want to test, then Craft can query against it in the next request. After the test all changes (`INSERT`s, `UPDATE`s, `DELETE`s) are rolled back, so you don't pollute your database with dummy data. More: ### Act as a logged-in user In order to test certain behaviour as a logged-in user, you don't need to fill and submit the login form. There is an `actingAs()` helper method as a shortcut. It accepts the email of an existing user, or you can create one on-the-fly using a factory. This feature is not fully documented so far, but it's a good opportunity to see that tests are also a good way of documenting code. Have a look at [tests/ActingAsTest.php](https://github.com/markhuot/craft-pest/blob/master/tests/ActingAsTest.php) to understand how it works. ```php actingAs('existing.admin@domain.com'); $this->get('/admin/actions/plugin-handle/controller/show')->assertOk(); }); ``` ### More complex examples Reading others' tests helps in writing your own. That's why we've created a test for the multi-step checkout process of the official Craft Commerce demo site: ## Closing thoughts When you start with testing, you will notice there is a lot of jargon that scares people away. Things like "mocks", "fakes", and "stubs" are terms you don't need to understand in the beginning. To learn testing you need to practice it. And at some point you will love it as it creates certainty when launching a site, and more importantly, when you introduce changes to an existing project. Once you are into it, when shipping something without test coverage you may get the feeling something is missing - at least this applies to me. ## Related Craft CMS reading - [Frontend testing for Craft CMS](/craft-cms-frontend-testing-with-codeception-and-cypress) — end-to-end alternative with Codeception and Cypress. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — performance tuning across the stack. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — tests are your safety net during a major upgrade. --- - [Craft CMS guides](/guides/craft-cms) # User account management with Craft CMS Source: https://blog.fortrabbit.com/craft-cms-user-account-management Created: 2023-02-09 Author: Piotr Pogorzelski Tags: webdev > Ready-to-use Craft CMS templates for registration, login, logout and password reset, with an explanation of how each of them works. ## Introduction One of the most commonly used interactive features of webpages is the user account system - visitors can create an account by registering, sign-in and sign-out. Craft CMS provides user management functionality out of the box with its [PRO edition](https://craftcms.com/knowledge-base/upgrading-to-craft-pro). Admins can add or remove users and also [assign them various roles and permissions](https://craftcms.com/docs/4.x/user-management.html) - to restrict specific user groups from visiting specific parts of the website or from performing some actions such as adding comments under blog articles. ### Why this article exists With Craft CMS, on the front-facing side of things, there are no ready to use forms and templates. Only controllers that accept form data. This should not surprise anyone that used Craft CMS before - Craft does not restrict developers to a specific set of themes or templates, it only provides the framework to build a website. This means that developers need to build frontend user interface themselves, which can be a little overwhelming. [Official documentation](https://craftcms.com/knowledge-base/front-end-user-accounts) provides example templates, these however are a bit limited in functionality. In this article, we will present a ready to use set of frontend user management templates and explain their inner workings. They are built with commonly used components and macros to ensure consistency. Inputs and other HTML elements have proper [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) attributes to make code accessible. ### What you will find here These are the pages that you will be able to use in your projects: - Login form. Ajax-based, displayed in a modal or on a separate page. - Registration and profile forms, automatically outputting any additional fields assigned to the user field layout. - Password reset and set new password forms. - Address form and list of addresses. The address form is also automatically outputting additional fields assigned to the address field layout. - Widget showing currently signed-in user and displaying links to user management pages. There is a [GitHub repository](https://github.com/craft-snippets/craft-user-templates) accompanying this article, where the whole Twig code lives. You can clone it and see how these templates work in practice or copy them into your Craft CMS project. ## Project structure Time to get to the meat of the matter. - Each page is represented by a Twig file in the `templates/_user` directory (all file paths will omit `templates` from now on). - Template code is highly modular, using reusable components - these are located in `_user/partials` directory. - URLs of the pages are set in the [config/routes.php](https://github.com/craft-snippets/craft-user-templates/blob/master/config/routes.php) file. - All page templates extend the [\_base.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_base.twig) file which is just a simple layout existing to showcase user management pages ### Base layout file The [\_base.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_base.twig) file contains basic HTML structure, simple CSS styles and link to the [Bulma](https://bulma.io/) CSS framework file. It also includes some components which are used on every page: - User widget file - [\_user/partials/user-widget](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/user-widget.twig). - Flash message component - [\_user/partials/flash-messages](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/flash-messages.twig).Flash messages are displayed only once and are used to show messages related to forms - errors or success notifications. - `

` header that uses the `pageTitle` variable defined in the specific pages and the `content` Twig block where specific pages inject their content. ### User widget The user widget component requires a bit of explanation. It functions as a simple navigation, allowing us to visit user management pages. - Craft CMS injects the `currentUser` variable into the template, which contains the currently logged-in [user object](https://docs.craftcms.com/api/v4/craft-elements-user.html). If nobody is logged in, this variable is set to `null` - thanks to that, we can choose which user management links should be displayed. - **login** and **registration** links will show up if the user has not logged in yet. After the user logs in, **profile**, **addresses**, and **logout** links will appear instead. The name of the current user will also be displayed. - **logout** is not actually a page but a route built-in into Craft CMS which can be changed using the [logoutPath](https://craftcms.com/docs/4.x/config/config-settings.html#logoutpath) general config variable. Remember that since content displayed by the user widget is dynamic, you need to avoid [caching](https://craftcms.com/docs/4.x/dev/tags.html#cache) it. ## Login form ![Login form page](/images/login-page.png) First, we will describe one of the most commonly used features of user management - the **login form**. The login form can be used in one of two ways: - As a separate page, possibly visited due to redirection from login-restricted content. - Displayed within the modal which showed up because the user clicked on a button or link. ### Login form page The login form page is available under the `login` address and lives in the [\_user/login-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/login-page.twig) template file. If you want to change the login address to something else in [config/routes.php](https://github.com/craft-snippets/craft-user-templates/blob/master/config/routes.php) file, remember to also change [loginPath](https://craftcms.com/docs/4.x/config/general.html#loginpath) in the general config. This setting defines the address where users are redirected when they try to access the login restricted page and need to sign in. When we take a look at `login-page` file, we will notice that it does not really output any HTML. It just includes `login-form` file which actually contains the form itself. This component is also used in login modals. `enableAutofocus` variable which is set to `true` and passed to `login-form` file makes sure that the cursor is focused automatically on the proper form field when we visit the login page. Why even add the possibility to disable autofocus? If we use our form within a modal, we don't want to focus the cursor on it when the page loads, because by default modal login form is hidden until the user decides to display it. The `login-page` file also contains [requireGuest](https://craftcms.com/docs/4.x/dev/tags.html#requireguest) Twig tag. If the user is already logged in, there is no need to see the login form, so the system will redirect the user either to the path defined in [postLoginRedirect](https://craftcms.com/docs/4.x/config/config-settings.html#postloginredirect) general config setting (by default it is the home page) or to login restricted page user tried to access. ### Login form component At the beginning of the `login-form` file, there are Twig objects which are later used to generate inputs using Twig macros. Using them, we can easily modify form contents. Most of the properties of these objects will be used to generate HTML elements using [tag](https://craftcms.com/docs/4.x/dev/functions.html#tag) Twig function. Note the label variables, `userNameLabel` and `passwordLabel` - they are set to static translation with the `app` param. This means that Craft CMS built-in static translations are used and our forms will be automatically translated if Craft provides a translation for a specific language. After defining form contents attributes, we use the Twig [embed](https://twig.symfony.com/doc/3.x/tags/embed.html) tag to extend the base form template - [\_user/partials/base-form.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/base-form.twig). This file is shared by all the forms described in this article and contains a `` tag with proper attributes (which we can modify by passing the `formAttributes` variable into this template) and CSRF protection functionality. `base-form` also contains a commented-out `_user/partials/model-errors` component - it displays all potential errors on top of the form. By default, it is not needed because inputs are set to display any possible errors next to a specific input. List of all errors can be still useful for debugging, so we decided to leave it like that. Now let's look at the `formContent` block where we place form contents. First, we need to take care of some hidden inputs which make sure that the login form works correctly. - [actionInput](https://craftcms.com/docs/4.x/dev/functions.html#actioninput) will direct the form request to the proper login controller. - [redirectInput](https://craftcms.com/docs/4.x/dev/functions.html#redirectinput) defines where the user ends up after successful login. It is set to the `craft.app.user.returnUrl` value, which will redirect the user to the login-restricted page he or she wanted to visit (or to the address set in the [postLoginRedirect](https://craftcms.com/docs/4.x/config/config-settings.html#postcploginredirect) general config setting, if we just visited login page directly). ### Form macros After the hidden inputs, we output visible form contents using Twig macros. Let's take a look at [\_user/partials/form-macros](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/form-macros.twig) file where macros are defined, and use `formFieldInput` macro as an example. This macro accepts three parameters - an object containing HTML attributes for input, input label text, and an array containing any potential errors to be displayed under input. At the beginning of the macro, there is an array containing default CSS classes used by input. If you include `class` property in the object containing input attributes, this class will be overwritten. Besides `formFieldInput`, there is also a macro for generating a checkbox - `formFieldCheckbox` and one for generating select fields - `formFieldSelect`. All of these macros internally use two other - `formLabel` for generating input labels, and `formField` for generating wrapper elements and displaying any potential errors. `formField` also adds `is-required` class to the field wrapper if we set the input as required. Thanks to the simple styling defined in [\_base.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_base.twig) file, fields with this class display a red asterisk after the label (with the exception of login form - it is kinda obvious that both login and password fields are both required). Thanks to these commonly used macros, all of our forms can be easily modified globally, for the whole website. All classes and other HTML attributes are defined in a single place. ### Ajax Login Our login form is now fully functional - but we can still make it better by adding AJAX functionality. To do that, we used the [progressive enhancement](https://www.smashingmagazine.com/2009/04/progressive-enhancement-what-it-is-and-how-to-use-it/) strategy - our form will work perfectly fine if JavaScript is disabled and AJAX is not available. With JavaScript enabled, thanks to the use of AJAX, our login form will not needlessly reload the whole page with every login attempt. In case of an unsuccessful login, it will just display an error message instead. This provides much a better user experience for users. The AJAX functionality code is placed within the [js](https://craftcms.com/docs/4.x/dev/tags.html#js) Twig tag, wrapped with a self-executing function to prevent any variable conflicts. Let's walk through this code - if you are not interested in the technical details, you can just skip this section. - First, we define messages which will be shown to the user. Unfortunately, such messages are not present in built-in Craft static message translations, so we use just regular static translations. - To grab the login form DOM elements, we use the `data-login-form` attribute. This is the same attribute we earlier set in the Twig variable `formAttributes` and passed to the `_user/base-form` template component. - Next, we loop through the DOM element collection, to make sure AJAX functionality is applied to both the regular login form and the login form present in the modal. - Within the `forEach` loop we attach to the `submit` event and use `e.preventDefault()` to prevent the regular submission of the login form. - Then we serialize form values using to `FormData` object and create an AJAX request. - Before the request starts, we add a loading class to the submit button (the class itself is taken from `data-login-form-button-loading-class` of the button) and a `disabled` attribute to the `fieldset` element - this will make the form disabled until the requests finish, to avoid sending multiple requests at once if user felt the sudden urge to keep clicking login button. - When the request is complete, we remove the loading class from the button and the `disabled` attribute from the fieldset, parse the server response from the JSON string, and act depending on the response code: - response code 200, login successful - the success message is put into the submit button. We either redirect the user to the URL returned by the server or just refresh the page if no redirect address was provided. - response code 400, login unsuccessful - we display an error message returned by the server using the regular `alert()` function. - response code 500, server error - we display a generic error message using the regular `alert()` function. - response code 0, connection error - we display a network error message using the regular `alert()` function. ### Login modal ![Login modal](/images/login-modal.png) The login form can be also displayed in a modal, using the [Modal component](https://plugins.craftcms.com/modal-component) plugin. Make sure you have it installed if you want to use it that way. The login modal is placed in [\_user/partials/user-widget](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/user-widget.twig) file, so it is available on every page. The modal plugin works by providing a modal template that can have modal content passed to it using the `embed` Twig tag. We just pass the login form there, with the `enableAutofocus` variable set to `false`. We also namespace the `id` and `for` attributes (using [apply](https://twig.symfony.com/doc/3.x/tags/apply.html) Twig function to apply [namespace](https://craftcms.com/docs/4.x/dev/filters.html#namespace) filter) of elements inside, to prevent conflicts and focusing on wrong input when someone clicks label. The modal is opened by clicking on the regular login link in the user widget which has `data-a11y-dialog-show` attribute set to `login-modal` - the same as `modalId` variable passed to the modal component. To make sure that the link does not redirect us to the login page just after opening modal, we attach a click event to it and run `preventDefault()` function. Keep in mind however that we can still open the login page in a new tab, using a middle mouse button. We also make sure that the autofocus functionality works after opening the modal - we use the modal component plugin event `show` for that. After opening the modal we just focus on input that has `data-enable-autofocus` attribute present. ## Resetting and setting a new password Craft CMS has a simple mechanism for resetting account passwords: - User enters the email address assigned to the account. - Message with reset link is sent to this email. - When the user visits the link from the message, he or she is redirected to the form where a new password can be set. As we can see, this requires two forms - **reset password form** and **set password form**. ### Reset password form ![Reset password form](/images/password-reset.png) This form is available under `reset-password` address. Remember that you can set the general config variable [setPasswordRequestPath](https://craftcms.com/docs/4.x/config/general.html#setpasswordrequestpath) to this URI so that Craft will redirect .well-known/change-password requests to the proper page. The password reset form is pretty simple - it has just one input, where users can enter their email. Template files used: - [\_user/password-reset-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/password-reset-page.twig) ### Set password form ![Set password form](/images/set-password.png) Users will visit this form after clicking the password reset link delivered by email. While Craft provides its own form for that functionality, we can replace it with our own. URL of **set password form** is set in general config under [setPasswordPath](https://craftcms.com/docs/4.x/config/general.html#setpasswordpath) to the default `setpassword` value. If no such page exists, Craft will use the default form - that's why we set this URI in [routes.php](https://github.com/craft-snippets/craft-user-templates/blob/master/config/routes.php) to form template. With only one visible input, the form itself is pretty simple. There are also two additional hidden inputs - `code` and `id`, which are filled by Twig variables injected automatically into a template based on the URL parameters of the password reset link. Note that if you reset the password of the admin user, Craft will still redirect you to the default built-in form, even if you have a custom form defined. Template files used: - [\_user/password-set-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/password-set-page.twig) ## Dealing with users Registration and profile forms are kinda similar - both deal with [user objects](https://craftcms.com/docs/4.x/users.html). The registration form creates new ones and the profile form edits existing users. Both of these forms inject `user` variable into the template in the situation when we submit the form, but the validation fails. When that happens, the form is populated with invalid values to inspect and correct them. When form is displayed before submitting, instead `user` variable we use: - Registration form - empty user object, created with [create](https://craftcms.com/docs/4.x/dev/functions.html#create) function. - Profile form - `currentUser` variable, containing currently logged-in user. ### User fields Both profile and registration forms share most of their fields - that's why these fields are placed into the separate reusable component, `user-fields`. The most interesting functionality of `user-fields` file is outputting the custom fields assigned to the user field layout. We retrieve them using the `user.getFieldLayout().customFields`, loop through them, and output each using the `custom-fields` template component. Inside that file, depending on the field type, field widgets are outputted using macros from `form-macros` template file. As for now, text, lightswitch, and dropdown fields are supported - the rest of the fields are ignored. Note that this component shows the username field only if [useEmailAsUsername](https://craftcms.com/docs/4.x/config/general.html#useemailasusername) setting is set to `false` - if we use email as username, there is no need for a separate username field. ### Registration form ![Registration form page](/images/sign-up.png) If you want to allow users to register, remember that you first need to enable it in the "Users" section of the control panel settings, with the "Allow public registration" setting. Craft CMS can verify the email address before the account is activated, using a verification email message. If this functionality is enabled in the settings, a flash message shown after the user submits the registration form will still be "User registered". We need to overwrite it with a proper message asking the user to confirm the account using email. To do that, we used [successMessageInput](https://craftcms.com/docs/4.x/dev/functions.html#successmessageinput) function. Template files used: - [\_user/register-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/register-page.twig) - [\_user/partials/user-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/user-fields.twig) - [\_user/partials/custom-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/custom-fields.twig) ### Profile form ![Registration form page](/images/profile.png) Profile form uses the same fields as the registration form, with a few additions: - `userId` hidden input, with the value set to current user id. Thanks to it, Craft knows which user to edit. - Photo field, which is only displayed if there is an asset source set for the user's photos in Craft CMS settings (otherwise, there would be nowhere to upload photos). - If a photo is already uploaded, it is displayed within the form, along with a checkbox that can be selected to remove the existing photo when the form is submitted. - New password field, used to change password. Remember that when the password is changed, users also need to fill **current password** field as a security measure. Same with changing the email address - otherwise, an error will appear when the form is submitted. Template files used: - [\_user/profile-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/profile-page.twig) - [\_user/partials/user-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/user-fields.twig) - [\_user/partials/custom-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/custom-fields.twig) ## Addresses [Addresses](https://craftcms.com/docs/4.x/addresses.html) are the element types introduced in Craft CMS 4. They are assigned to the users and can have their own field layout composed of native fields (pre-existing, specific only to address) as well as regular Craft fields. To manage addresses on the frontend, we need to have three pages: - Addresses list - New address page - Edit address page ### Address list ![Addresses page](/images/addresses.png) The address list displays all addresses belonging to the currently logged in user. It also has a link to the **new address** page. Each address on the list has: - Address title. - Link to **edit address** page. - Deletion form. Visually, this form shows only the delete button, but it also contains [actionInput](https://craftcms.com/docs/4.x/dev/functions.html#actioninput) set to `users/delete-address` controller action. To tell Craft which address should be deleted, there is also `addressId` hidden input. Template files used: - [\_user/address-list-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/address-list-page.twig) ### New address page Just like with **profile** and **registration** pages, the **new address** page and **edit address** page use the common template component for displaying its contents, `address-fields`. Within this file, we loop through address field layout items. These consist of both regular Craft fields which are just outputted using `custom-fields` template, or native address fields. These are outputted manually within the `address-fields` template component, using Twig macros. Note that a single native field is sometimes represented by multiple inputs. For example, **Latitude/Longitude** field is represented by two separate inputs in the form - one for latitude and one for longitude. Depending on the option selected within **Country** select widget, Craft CMS may validate **Postal code** and **State** inputs as either required or not. For example, for the USA these inputs are required. That's why this form uses `required` HTML attribute for both of these inputs by default. Template files used: - [\_user/address-new-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/address-new-page.twig) - [\_user/partials/address-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/address-fields.twig) - [\_user/partials/custom-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/custom-fields.twig) ### Edit address page ![Address edit page](/adress-edit.png) Users can have multiple addresses assigned. Since Craft does not provide frontend URLs for addresses, the route for a specific address page needs to use `addressId` token. Using this ID, the template code performs the element query and grabs a specific address to populate the address form. If no address with a specific ID is found, the template just throws 404 error. Using the queried address object, we also define `pageTitle` containing the address title. Template files used: - [\_user/address-edit-page.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/address-edit-page.twig) - [\_user/partials/address-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/address-fields.twig) - [\_user/partials/custom-fields.twig](https://github.com/craft-snippets/craft-user-templates/blob/master/templates/_user/partials/custom-fields.twig) ## Closing thoughts With this set of templates, your Craft CMS website will support user accounts - but the fun does not stop there. Twig components and macros we described in this article can easily be repurposed for other things. For example - for building [Entry form](https://craftcms.com/knowledge-base/entry-form). And even if you don't need any forms - our code is a good example of how to build Twig templates in a modular and robust way. ## Related Craft CMS reading - [3 ways to reset the Craft CMS control panel password](/three-ways-to-reset-the-craft-cms-control-panel-password-without-email-access) — admin recovery when email is offline. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — performance tips for high-traffic auth endpoints. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — the user system changed in v4. _This article is [cross-published at the website of the author](https://craftsnippets.com/articles/user-account-management-with-craft-cms)._ --- - [Craft CMS guides](/guides/craft-cms) # Craft Copy 1.0 released Source: https://blog.fortrabbit.com/craft-copy-1-released Created: 2020-11-12 Author: Frank Lämmer Tags: webdev > Our command line tool to help with Craft CMS deployment on fortrabbit is now production grade ready. ## How to get it? You can grab it from [Craft plugin store](https://plugins.craftcms.com/copy) or directly from [GitHub](https://github.com/fortrabbit/craft-copy). ## Some history Two years ago [we initially announced Craft Copy](/introducing-craft-copy): CLI deployment tools for Craft CMS Apps running on fortrabbit. During the last two years we have refactored and hardened the tool. Thanks to the testers and early adapters for sharing feedback and [issues on GitHub](https://github.com/fortrabbit/craft-copy). We now see around [5.500 installs on packagist](https://packagist.org/packages/fortrabbit/craft-copy) and maybe more precise around [700 installs](https://plugins.craftcms.com/copy) on the Craft plugin store. THANKS! ## What problem does it solve? Understand that it takes the following data types to sync your local changes up and down to your hosting environment. 1. Your code: configuration and templates 2. The CMS code: pulled in by Composer 3. Assets: content images 4. MySQL database: the contents themselves 5. ( Artifacts: compiled JS & CSS ) Since Craft CMS is ready for Git and also using Composer, it is easy to use `git push` to deploy these changes to fortrabbit (point 1 & 2). But we wanted to have something convenient for the other data types as well. Craft Copy provides shortcuts for syncing assets, folders and the database up and down (points 3 - 5). Craft Copy also contains some other magic to overcome certain gotachs, like settings for different MySQL versions, it also will create a predefined `.gitignore` file. ## How to use it? Please best follow our README here: [github.com/fortrabbit/craft-copy](https://github.com/fortrabbit/craft-copy) ## What are the latest changes? With the latest released we have changed the way assets are handled. Now Craft Copy will iterate over the defined volumes. There also is a new command to sync folders. Please see the release notes for more: [github.com/fortrabbit/craft-copy/releases/tag/1.0.0)](https://github.com/fortrabbit/craft-copy/releases/tag/1.0.0) ## Next steps * We plan to promote to use Craft Copy as our standard recommendation to deploy Craft Copy in our [help pages](https://help.fortrabbit.com/craft-3-about). * We have a [milestone 1.1 planned](https://github.com/fortrabbit/craft-copy/issues?q=is%3Aopen+is%3Aissue+milestone%3A1.1). Contributions welcome! # We are a Craft Hosting Partner Source: https://blog.fortrabbit.com/craft-hosting-partner Created: 2017-07-25 Author: Oliver Stark Tags: chronicles > fortrabbit becomes one of the first official Craft CMS hosting partners, after three years of hosting Craft projects on the platform. ## Hosting Craft since 2014 We are hosting Craft projects for quite a while now. The first sites on Craft appeared here three years ago — shortly after Craft 2.0 was released. Since only a few customers used it, we didn't payed much attention to this newcomer CMS. In late 2015, in preparation for my [CMS Quo Vadis blog post](https://blog.fortrabbit.com/cms-quo-vadis) I took a deeper look at various CMS, including Craft. Besides technical features and ease of use, size and activity of the developer community are probably the most important factors to determine the maturity of software. I was impressed. Today we are running hundreds of sites powered by Craft. We are excited to see the Craft community growing here on fortrabbit. ![Software distribution on fortrabbit](/images/software-distribution-on-fortrabbit.png) ## What we like about Craft It feels like there is literally no other CMS that gets more [love on twitter](https://twitter.com/search?f=tweets&vertical=default&q=craftcms%20love&src=typd) these days. People really enjoy building sites with Craft. There so many [blog](https://wildbit.com/blog/2016/11/01/how-we-chose-craft-cms-for-products-websites) [post](http://madebykind.com/blog/why-we-love-craft-cms/) [out](https://weareabstrakt.com/blog/2017/why-content-managers-love-craft-cms/) [there](https://madebyshape.co.uk/web-design-blog/we-love-craft-cms) that highlight features and benefits, there is not much more to add. We are excited about the beautifully designed sites that appear here every day. And we enjoy working with the people who make this happen. ## Why host Craft on fortrabbit? Yes, you can host your Craft CMS project nearly everywhere. However, most hosting services have limited experience with Craft as they focus on WordPress and Drupal or the service is just generic where everything or nothing is possible. As your official Craft Hosting Partner, we do have an understanding how Craft works. And in case you are stuck somewhere: we do our best to help out. Craft runs smoothly on both [fortrabbit stacks (Universal + Professional)](https://help.fortrabbit.com/stacks). fortrabbit is more than just raw hosting resources. It's a managed platform with a unique tool-set to help agencies working for clients in a team more efficiently: from role based team permissions, to private Git repos and managed backups. ## New to Craft? Like with any other CMS, getting started with Craft requires you some new stuff to learn. Fortunately, the community will help. Find them on [Slack](https://craftcms.com/community), on [StackExchange](https://craftcms.stackexchange.com/) and at [local meet-ups](https://www.meetup.com/topics/craft-cms/). ### Ready to pay for a CMS? One deal-breaker might be the price tag. Are you willing to pay for a CMS, while the other options are free? That's up to you. Think about your time. Maybe Craft will get you to the same point in less time with a better result? When working for a client, these costs might not play a major role. ### More to discover - [Craft 2 install guide - fortrabbit](https://help.fortrabbit.com/install-craft-2-uni) - [Craft 3 install guide (beta) - fortrabbit](https://help.fortrabbit.com/_WIP/install-craft-3-uni) - [Official Craft 2 Docs](https://craftcms.com/docs/introduction) - [Official Craft 3 Docs](https://github.com/craftcms/docs) - [Andrew Welch's Blog](https://nystudio107.com/blog) - [John Morton's Bi-weekly Newsletter Craft Link List](http://craftlinklist.com) - [Ryan Masuga's The Guide to Craft CMS Development](https://gomasuga.com/course/craft-cms-guide) - [Ryan Irelan's Video courses at Mijingo (It's like Laracasts for Craft)](https://mijingo.com/) - [Jeff Bridgforth: Craft vs. WordPress](https://b.dboy.com/craft-vs-wordpress-8628634c09a7) You can find the official announcement here at [craftcms.com](https://craftcms.com/news/craft-hosting-partners). # Image processing in Craft CMS with the Image Toolbox plugin Source: https://blog.fortrabbit.com/craft-image-transform-toolbox Created: 2023-07-26 18:15:31 Author: Piotr Pogorzelski Tags: webdev > The Image Toolbox plugin for Craft CMS builds responsive pictures with WebP variants and generates placeholders when an image is missing. ## Introduction Craft CMS offers developers a robust functionality for [transforming and processing](https://craftcms.com/docs/4.x/image-transforms.html) images uploaded through its control panel, allowing for seamless integration with templates. Leveraging the power of image transforms, developers can effortlessly modify image proportions, size, format, and more. While this functionality provides a solid foundation, Craft CMS does not support more advanced functionalities out of the box, such as automatically generating WebP versions of images, implementing responsive images, and automatically creating image placeholders for missing images. Recognizing the need for a simple solution to introduce these functionalities, I created [Image toolbox](https://plugins.craftcms.com/image-toolbox?craft4) plugin. In this article, I will present practical examples of how this plugin can be used. ## Picture HTML tag Image Toolbox does not replace Craft CMS images transform engine - it is strictly a templating tool. It uses either native Craft CMS image transforms or these provided by [Imager-x plugin](https://plugins.craftcms.com/imager-x?craft4). Imager toolbox main feature is outputting images using the [picture HTML tag](https://craftsnippets.com/docs/image-toolbox/Picture.html#picture-html-element). This tag works similarly to the standard img tag, but it also offers a very useful feature - it can contain multiple `source` tags within itself, each using a separate image URL, and displayed under specific conditions. This is particularly useful for presenting browsers with multiple versions of image to choose from. ## WebP version of images WebP is an image format that has gained popularity in recent years. Compared to JPG, it can offer 30% to 50% savings in image size, resulting in significant bandwidth savings when it is used. But if we want to use the WebP version of an image, can't we just use regular Craft CMS image transforms and set the `format` to `webp`? The problem lies in the fact that WebP is not universally [supported by all browsers](https://caniuse.com/webp). While the latest versions of modern browsers support it, Safari browsers on older Apple devices do not. This is especially problematic since Safari on these devices cannot be updated to the latest version. This is where the picture element comes in handy. Thanks to multiple source elements, we can [output both the WebP and the original format](https://craftsnippets.com/docs/image-toolbox/Picture.html#webp-variants-of-images) version of an image. The browser will obviously not download both of these versions (this would go against our goal of saving bandwidth using the WebP format). If the browser supports WebP, this format of the image will be loaded; otherwise, the original format will be loaded. Here's a simple example where we output a transformed version of an image using the [craft.images.pictureMultiple()](https://craftsnippets.com/docs/image-toolbox/Picture.html#picturemultiple-method) function. ```twig {% set someAsset = entry.imageField1.one() %} {% set settings = [ { asset: someAsset1, transform: { width: 200, height: 500, mode: 'crop', }, } ] %} {% set htmlAttributes = { class: 'some-class', } %} {{ craft.images.pictureMultiple(settings, htmlAttributes) }} ``` This function accepts a nested array of objects. In our example, we have only one object, but we can include multiple objects for the sake of responsive images functionality, which will be explained later. The transform sub-object follows the regular Craft CMS transform syntax. Image Toolbox will create such a transform with two versions: one in the original format and one in WebP. The function also accepts an optional second attribute, which is an array of HTML attributes to be applied to the rendered picture. Here is the generated HTML: ```twig ``` As you can see, we have two sources, each with a different type attribute, allowing the browser to select the correct one based on its format support. The picture element also contains a fallback `` tag, which would be used if the browser does not support the picture element at all. Any attributes applied to this tag will be applied to the entire picture element. It's worth noting that if we explicitly specify that we want the WebP format in the transform settings, only the WebP version will be outputted. Image Toolbox is also smart enough not to try to convert SVG images to WebP, as SVG has its own unique qualities as an image that would be lost during WebP transformation. ## Responsive images with multiple variants The picture element, along with [multiple source elements](https://craftsnippets.com/docs/image-toolbox/Picture.html#picture-with-multiple-breakpoint-variants), empowers the implementation of responsive images. This approach extends beyond format support, encompassing screen size and media queries. By offering diverse image sources that can differ in format, resolution, or art direction, we dynamically adapt and deliver the ideal image based on the viewer's device and context. This flexibility guarantees an optimal visual experience across different screens and browsing conditions. One may wonder, why can't we use two regular img tags and employ CSS breakpoints and `display: none;` to toggle their visibility. Such approach falls short as hiding images through CSS does not prevent the browser from downloading their contents. Consequently, when implementing responsive images with multiple variants, this method would result in increased bandwidth usage. Let's use the `craft.images.pictureMultiple()` function again. This time, we will provide it with multiple assets and transform settings. Each object representing a source has an additional `media` property. ```twig {% set settings = [ { asset: someAsset1, transform: { width: 200, height: 500, mode: 'crop', }, media: '(min-width: 1024px)', }, { asset: someAsset2, transform: { width: 100, height: 100, mode: 'crop', }, media: '(max-width: 1023px)', } ] %} {% set htmlAttributes = { class: 'some-class', } %} {{ craft.images.pictureMultiple(settings, htmlAttributes) }} ``` Here is the generated HTML code: ```twig ``` In this example, the browser will not only select the source based on WebP support but also on the media query. Different sources can use different assets, but you can also use the same asset for all and differentiate them only by the transform settings. If you don't want to display any image at all on a specific breakpoint, simply set both the asset and transform to `null`. The Image Toolbox will output an empty transparent pixel for the specific source in this case. Instead of passing the entire media query into the source settings, you can also use just the `min` or `max` attributes, like this: ```twig {% set someAsset1 = entry.imageField1.one() %} {% set someAsset2 = entry.imageField2.one() %} {% set settings = [ { asset: someAsset1, transform: { width: 200, height: 500, mode: 'crop', }, min: 1024, }, { asset: someAsset2, transform: { width: 100, height: 100, mode: 'crop', }, max: 1023, } ] %} {{ craft.images.pictureMultiple(settings) }} ``` This will generate the same HTML code as the first example. ## Using responsive images with Transform Layouts If you are utilizing specific image transforms and breakpoints in multiple template files and want to avoid duplicating code, you can use [transform layouts](https://craftsnippets.com/docs/image-toolbox/Layouts.html). They are defined in the [plugin's configuration file](https://craftsnippets.com/docs/image-toolbox/Settings.html), with `transformLayouts` setting. By using this setting, you can conveniently centralize the definition of your image transforms, making it easier to manage and maintain consistent transformations across various templates. Let's define a transform layout with the handle `someHandle` in the `config/image-toolbox.php` file: ```php 'transformLayouts' => [ 'someHandle' => [ 'variants' => [ [ 'media' => '(max-width: 999px)', 'transform' => [ 'width' => 300, 'mode' => 'crop', ] ], [ 'media' => '(min-width: 1000px)', 'transform' => [ 'width' => 600, 'mode' => 'stretch', ] ] ], 'attributes' => [ 'class' => 'some-class' ], ], ], ``` As you can see, the syntax is quite similar to the one used by the Twig `craft.images.pictureMultiple()` function. However, it omits the assets, which need to be provided from the template. To output picture with Transform Layout, we can use `craft.images.layout()` function: ```twig {% set someAsset1 = entry.imageField1.one() %} {% set someAsset2 = entry.imageField2.one() %} {{craft.images.layout([someAsset1, someAsset2], 'someHandle')}} ``` In this example, `someAsset1` will be used for the first source element, and `someAsset2` for the second one. If you want all sources to share the same asset, simply pass a single asset to the function, and the Image Toolbox will use it for all sources, like this: ```twig {% set someAsset = entry.imageField.one() %} {{craft.images.layout(someAsset, 'someHandle')}} ``` Using transform layouts offers one more advantage. HTML attributes applied to the picture element can be dynamically calculated based on the asset objects. This can be achieved using an anonymous PHP function: ```php 'transformLayouts' => [ 'someHandle' => [ 'variants' => [ [ 'media' => '(max-width: 999px)', 'transform' => [ 'width' => 300, 'mode' => 'crop', ] ], [ 'media' => '(min-width: 1000px)', 'transform' => [ 'width' => 600, 'mode' => 'stretch', ] ] ], 'attributes' => function($assets){ if(!is_null($assets[0])){ if($assets[0]->getFieldValue('someField') != ''){ $title = $assets[0]->getFieldValue('someField'); }else{ $title = $assets[0]->title; } }else{ $title = null; } $attrs = [ 'title' => $title; ]; return $attrs; }, ], ], ``` In the example above, we use the first asset passed to the layout method to determine the title attribute value for the picture element. If the field using `someField` handle, assigned to the asset, has content, we use it as the title. If it is empty, we use the asset's own title attribute instead. If the asset is missing, we simply exclude the title attribute from the output. By placing this code in PHP configuration file, we can make our Template code simpler and more robust. ## Image placeholders Using [image placeholders](https://craftsnippets.com/docs/image-toolbox/Placeholders.html) offers several benefits. They can be employed during the development phase of a website or when an actual image is missing. Placeholders play important role in maintaining the layout and structure of the page, ensuring that missing images do not alter the overall appearance of the website. In Craft CMS, the `one()` method of the element query returns null when an asset is missing from a specific field. Therefore, when we pass null instead of an asset object to Image Toolbox functions, it generates a placeholder image for that source within the picture element. The placeholder image utilizes the width and height settings from the provided image transform, preserving the same proportions as the actual image would have. If only the width or height attribute is set in the transform, Image Toolbox creates a square placeholder with both dimensions set to the same provided value. Image Toolbox offers three methods of generating placeholders: * Svg mode: Outputs a transparent SVG image as the placeholder. * Url mode: Utilizes an external placeholder generation service, such as [placehold.co](https://placehold.co/). * File mode (default): Generates placeholders by using a specific base image as the base and adding empty space at the sides or top and bottom to ensure the placeholder maintains the same proportions as the missing image. The placeholder mode can be changed using the `placeholderMode` [plugin setting](https://craftsnippets.com/docs/image-toolbox/Settings.html); however, it is usually best to leave it in file mode. In file mode, the placeholders utilize the default gray source graphic provided by the plugin, but it is simple to change it to any other image (using the `filePlaceholderPath` setting) to fit the website's graphical design. Additionally, you can customize the color of the empty space added to the placeholders (using the `filePlaceholderBackgroundColor` setting). Below there is an example transformed image and placeholder generated from the same set of transform settings. As you can see, base placeholder image has empty space added to the sides make it same proportions as the missing image. ![](/images/craft-image-toolbox-placeholder2.png) ## Image variants field All functionalities described so far belong to **Lite** version of the plugin, which is available for free. If you want to provide your admin panel users with more control over your images, you can utilize the [Image Variants field](https://craftsnippets.com/docs/image-toolbox/Field.html), available in the **Pro** version, costing 19$. With the Image Variants field, you can configure picture variants with transform and breakpoint settings for all images in the asset source. Additionally, you can specify whether the pictures should use width and height attributes or have webp variants generated for their sources. These settings can be assigned to the asset source field layout and defined in the **field settings**. Moreover, you can override this configuration for specific assets by defining settings in the **field values** of those assets. To output picture with configuration defined using **Images variant** field, you can use `pictureFromAsset()` method: ```twig {% set img = entry.someAssetField.one() %} {% set htmlAttributes = { class: 'some-class', } %} {{craft.images.pictureFromAsset(img, 'variantField', htmlAttributes)}} ``` In this example, `variantField` is handle of the Image Variants field assigned to the asset source. Below is a screenshot showcasing the Image Variants settings, with three picture sources defined: ![](/images/craft-image-toolbox-variants-field.png) ## Alternative solution - ImageOptimize plugin An alternative to the Image Toolbox plugin is [ImageOptimize](https://plugins.craftcms.com/image-optimize?craft4). This plugin also provides functionality for generating responsive images; however, it does not include automatic placeholder and WebP version generation. Instead, it offers lazy loading functionality, which displays a lightweight silhouette until the actual image loads. Similar to the PRO version of Image Toolbox, ImageOptimize offers a control panel interface using fields assigned to asset sources. In terms of pricing, ImageOptimize is priced at $59, whereas the PRO version of Image Toolbox costs $19. ## Summary In conclusion, the [Image Toolbox](https://plugins.craftcms.com/image-toolbox?craft4) plugin for Craft CMS enhances the image processing capabilities of the platform, offering advanced functionalities that are not available out of the box. By providing seamless integration with basic image transform system, it empowers developers to effortlessly generate WebP versions of images and implement responsive images with multiple variants. The plugin's ability to generate image placeholders further contributes to maintaining the layout and structure of a website, ensuring a consistent visual experience even when images are missing. With this set functionalities, Image Toolbox proves to be very useful tool for developers looking to optimize image delivery on Craft CMS-powered websites. ## Further reading * [Image toolbox in the Craft plugin store](https://plugins.craftcms.com/image-toolbox) * [Image toolbox plugin documentation](https://craftsnippets.com/docs/image-toolbox/) ## Related Craft CMS reading - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — image work is often a top performance lever. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — what to know before upgrading. - [User account management with Craft CMS](/craft-cms-user-account-management) — more practical Twig-template patterns. _DISCLAIMER: fortrabbit has co-sponsored this blog post. It's cross published here. The original version can be found over at [craftsnippets.com](https://craftsnippets.com/articles/image-processing-in-craft-cms-with-image-toolbox-plugin)_ --- - [Craft CMS guides](/guides/craft-cms) # Craft Nitro 2 first look: How to quickly set up a local Craft CMS dev site Source: https://blog.fortrabbit.com/craft-nitro-2-first-look-how-to-quickly-set-up-a-local-craft-cms-dev-site Created: 2021-05-27 Author: Jascha Silbermann Tags: webdev > Craft Nitro 2 dropped Multipass for Docker. A first look at setting up a local Craft CMS development site with it. ## Introduction We previously tried out Craft Nitro when version 1.0 was released. Due to the tool's reliance on the Multipass virtualization technology, we didn't get very far. We ended up recommending [DDEV to run a local Craft site](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup#ddev) instead. However, with the release of version 2.0, Craft Nitro has become an even more viable option. Here we like to show you how to: 1. Get Craft Nitro 2 up and running on your machine. 2. Use Nitro to run existing or new Craft sites. ### Nitro 2 and Craft Copy: not ready to be best friends, at least not yet 😢 We had hoped to also be able to show you how to use fortrabbit's Craft Copy tool with Nitro to sync your Craft site to your fortrabbit Apps. Unfortunately, that's not currently possible due to some limitations in the environment Nitro provides. You can [read more about why at the end of this article](#craft-copy). ### The Craft Nitro 2 development tool Made by Pixel & Tonic - the people behind Craft CMS - Craft Nitro 2 is: * A Docker-based command-line tool for **local development**. * Meant to be **easy to setup and use**. * Unlike most other dev tools, Craft Nitro 2 is specifically geared towards **Craft CMS development**. ### Installation requirements Craft Nitro 2 sits on top of Docker and **works on macOS, Linux, and Windows**. The installation will be shown for macOS, using the Homebrew package manager. To install on Linux you can also use Homebrew; the steps will be almost identical. The same works for Windows, provided your system has the Windows Subsystem for Linux (WSL) installed. For this installation procedure, you will need: 1. Basic knowledge of the **command line**. 2. The **Homebrew package manager** installed. ↳ Install Homebrew on [macOS](https://brew.sh/) ↳ Install Homebrew on [Linux or Windows Subsystem for Linux](https://docs.brew.sh/Homebrew-on-Linux) We've **completed installation** using the following software / package versions: | Software | Explanation | Version | |:--|:--|--:| | macOS Catalina | Operating system | `10.15.7` | | zsh | Shell | `5.7.1` | | Homebrew | Package manager | `3.1.4-22-gc11067c` | | Docker Desktop | Container virtualization | `3.2.2` | | Craft Nitro | Craft CMS dev tool | `2.0.7` | ## Install Craft Nitro 2 to power your local Craft CMS dev sites The first step is to install Docker Desktop. If you already have Docker installed you can skip this bit. At the time of writing, the **minimal supported Docker version is 3.0**. Make sure to check the official [Craft Nitro 2 installation requirements][nitro-install] for up-to-date instructions. 1. Let's go ahead and **install Docker Desktop**: ```sh # install Docker Desktop brew cask install docker ``` 2. Once we have Docker installed we need to **launch the app at least once** to complete the configuration. ```sh # make sure to run the Docker App once before proceeding! open /Applications/Docker.app/ ``` 3. Next, we **install Craft Nitro 2**: ```sh # install Craft Nitro 2 brew install craftcms/nitro/nitro ``` If you're using a **different operating system**, or are uncomfortable using `brew`, check the official [Craft Nitro 2 installation instructions][nitro-install] to find alternative means of installing Craft Nitro 2. ### Things to consider before setting up Craft Nitro 2 Having installed Docker and Craft Nitro 2, we continue by initializing Nitro. The initialization procedure is interactive; we'll be asked to make a few **basic choices, such as which database(s) to use**. The choices made during initialization are saved in the `'.nitro/nitro.yaml'` file inside the user's home directory. As such, Craft Nitro 2 settings are user account-specific. Before we can get started, we need to answer a couple of questions: 1. Do you have **another dev tool installed** on your machine? Nitro's default settings require ports `80` and `443` to be available. If another dev tool, such as DDEV or Lando, is already installed these ports will likely be taken. In this case, we'll have to use custom ports for Nitro. 2. Are you **working under an account with admin privileges**? Nitro wants to edit the hosts file when initializing. This requires `sudo` privileges, so initialization needs to be run as an admin user. A standard macOS user account has admin privileges enabled. However, [recommended best practice](https://www.bsi.bund.de/DE/Themen/Verbraucherinnen-und-Verbraucher/Informationen-und-Empfehlungen/Cyber-Sicherheitsempfehlungen/Basisschutz-fuer-Computer-Mobilgeraete/Basisschutz-fuer-Computer/Benutzerkonten/benutzerkonten_node.html) is to work under a non-admin account. If you're not working as an admin user, you'll need to turn off host file editing and add the hosts file entries yourself. ### Initializing Craft Nitro 2 For this installation procedure, we'll assume that we're on a machine: * with other **dev tool(s) installed**, * working as a **user with admin privileges**. Before starting the initialization, **we'll set custom ports for Craft Nitro 2**. We'll also explicitly tell Nitro to use the `'.nitro'` top-level-domain (TLD) for its local host names. We apply these customizations by setting a few [Craft Nitro 2 environment variables](https://craftcms.com/docs/nitro/2.x/customizing.html#nitro-environment-variables) to appropriate values. To do so, we copy the following commands into a terminal and run them: ```sh # set environment variables export NITRO_HTTP_PORT='8080' export NITRO_HTTPS_PORT='8443' export NITRO_DEFAULT_TLD='nitro' # uncomment next line to turn off hosts file editing # export NITRO_EDIT_HOSTS='false' # initialize Craft Nitro 2 nitro init ``` Once the environment variables have been set, **we continue to initialize Craft Nitro 2**. Again we're asked to make a number of choices. These will depend on your specific setup; we've documented ours here: | Craft Nitro 2 `init` step | Value | |:--|:--| | Would you like to use MySQL [Y/n]? | `y` | | Select the version of MySQL | `1` (MySQL 8.0) | | Would you like to use PostgreSQL [Y/n]? [Y/n] | `n` | | Would you like to use Redis [Y/n]? | `n` | ## Set up a local Craft CMS dev site with Craft Nitro 2 In this section we'll show how to **set up a fresh Craft CMS site with Craft Nitro 2** for local development. In case you want to use Nitro to power an existing Craft CMS dev site, please refer to the section [using Craft Nitro 2 with an existing Craft CMS installation](#existing-craft-site-with-nitro2) below. We'll use the `'nitro create'` command to set up a local Craft CMS dev site. This command uses Composer inside the container, so there's **no need to have Composer installed locally** — nice! Please refer to the [official Craft CMS installation guide][craft-install] for other means of installing. We'll kick of creation of our new Craft CMS site via the following command: ```sh # create a new Craft CMS dev site on the Desktop cd ~/Desktop && nitro create fortrabbit ``` The `'nitro create'` command runs interactively, presenting us with a set of choices. We've documented ours here: | Craft Nitro 2 `create` step | Value | |:--|:--| | Enter the hostname [fortrabbit.nitro] | `` | | Enter the webroot for the site [web] | `` | | Choose a PHP version | `1` (PHP 8.0) | | Add a database for the site [Y/n] | `y` | | Enter the new database name | `fortrabbit` | | Should we update the env file? [Y/n] | `y` | After creation, a new container for our site should be up and running. We can test this by issuing the `'nitro ls'` command. This command **lists all running Nitro containers** along with their status. Let's continue by setting up Craft CMS. To do so, we'll **log into the site's container and run the Craft CMS setup** from there. Since we asked Craft Nitro 2 to update the site's `.env` file, we want to use those settings. Use the following set of commands to get your site set up. Make sure to **adapt the settings** underneath ">>> provide your site settings here <<<" to suit your needs. We recommend you copy-paste each commented block of code into your terminal and run them there. ```sh # log into the container nitro ssh fortrabbit # make sure we're in the correct directory cd /app/ # load existing settings from .env file source .env # run Craft CMS database setup in non-interactive mode # using settings loaded from .env ./craft setup/db --interactive=0 --driver='mysql' --server="$DB_SERVER" --port="$DB_PORT" --database="$DB_DATABASE" --user="$DB_USER" --password="$DB_PASSWORD" # >>> provide your site settings here <<< adminEmail='craftadmin@fortrabbit.nitro' adminUser='craftadmin' adminPassword=$(openssl rand -base64 32) siteName='fortrabbit Craft Nitro' siteUrl="http://fortrabbit.nitro:8080" # install Craft CMS in non-interactive mode ./craft install --interactive=0 --email="$adminEmail" --username="$adminUser" --password="$adminPassword" --siteName="$siteName" --siteUrl="$siteUrl" && printf "\n- Your password for user '${adminUser}' is:\n\n${adminPassword}\n\n-Your site should be live at:\n\n${siteUrl}\n\n" && exit ``` A couple **things to note**: * We've **initialized Craft Nitro 2 using custom ports**. We need to append the port number to the site URL: `http://fortrabbit.nitro:8080/`. Otherwise, our site won't load. * We've used the **settings stored in the `.env` file**. For debugging, we can print out those settings while inside the container by issuing a `'cat /app/.env'` command. Our site should now load in the browser — **make sure to test it works**! ## Use Craft Nitro 2 to power an existing Craft CMS dev site Maybe you'd like to **run an existing Craft CMS project via Craft Nitro 2**. In this case, we'll use the `'nitro add'` command instead of `'nitro create'`: 1. Go to your local Craft CMS project directory: ```sh cd ``` 2. Add the site to Craft Nitro 2: ```sh nitro add . ``` Here, we're given a similar set of choices as for the `'nitro create'` command. You may find our choices in the section on [setting up a new Craft CMS site](#new-craft-site-with-nitro2). 3. Import your local database backup: ```sh nitro db import ``` ### Craft Nitro 2 and Craft Copy Over the years, fortrabbit has contributed to the Craft CMS ecosystem. We've published plugins, guides and blog posts. The latest exciting development is fortrabbit's own [Craft Copy tool](https://blog.fortrabbit.com/craft-copy-1-released). Craft Copy **syncs all components of a Craft site, up and down**. This includes your custom code, as well as assets, database contents and the Craft CMS code. As an added bonus, Craft Copy supports advanced use cases, such as [multiple staging environments](https://github.com/fortrabbit/craft-copy/#multi-staging-config). We previously showed how to [integrate Craft Copy with DDEV](https://blog.fortrabbit.com/local-craft-dev-site-ddev-development-tool#deploy-to-hosting-platform). Naturally, we attempted to do the same with Craft Nitro 2. Unfortunately, here we ran into an issue. Craft Copy uses Git and Rsync with SSH keys under the hood. To use the tool, one **needs to install the SSH keys associated with your fortrabbit account within the container**. To our surprise, Craft Nitro 2 lacks the capability to import SSH keys from the host machine — [see this GitHub issue](https://github.com/craftcms/nitro/issues/297). It also does not have the other dependencies (`ssh`, `rsync`, `zcat`) available inside its container that Craft Copy needs in order to work. At time of writing, the only way to use Craft Copy with Craft Nitro 2 is to run Craft Copy from outside the container. But this is not preferred: using the tool outside the container **requires its dependencies to be installed on the user's local machine**. Such an approach opens the door for version conflicts and similar headaches. Certainly not something we want to recommend. That said, Pixel & Tonic have a great track record of responding to demand from the Craft CMS community, so it's possible they will update Nitro in future to allow better integration with other tools. If this is something you'd like to see, consider [letting them know](https://github.com/craftcms/nitro/issues/). ## Conclusion A fair share of fortrabbit's client base use our infrastructure to host their Craft CMS sites. This includes less technically-minded folks, for whom setting up a local dev sites is a real challenge. So we'd love to have a **single, integrated solution to recommend**. Initially, Craft Nitro 2 looks really promising in this regard. Craft Nitro 2 ships with a handful of useful commands, including `'nitro composer'`, `'nitro php'`, `'nitro craft'`, and `'nitro npm'`. These allow us to issue `composer`, `php`, `craft`, and `npm` commands inside the container. This absolves the user of the responsibility of installing and maintaining these tools on their own machine. Instead, the **dependencies live inside the container**. We love it, as that reduces the surface area for version conflicts and related confusion. While **Craft Nitro 2 does a good job** at quickly getting a local Craft CMS dev site up and running, when it comes to the more sophisticated aspects of Craft CMS development, DDEV still pulls ahead. We really hope to see Host SSH key support added to Craft Nitro 2 soon. When that happens we'll be happy to give it another shot. For now, we'll **continue to recommend DDEV to our clients** as the go-to solution for local Craft CMS development. Summing up, here are some of the **strong points of Craft Nitro 2 and DDEV** compared: | Feature | Nitro | DDEV | |:--|:--|:--| | Supports Craft CMS | Explicitly | Implicitly via PHP recipe | | Set up as non-admin user | Doesn't seem to be supported | Straightforward via admin account | | Use local host names | Requires editing hosts file | Implemented via `*.ddev.site` lookup | | Dedicated commands for dependencies inside container | Craft, Composer, PHP, NPM | Composer, PHP | | Use SSH keys inside container | Currently unsupported | Supported via `ddev auth ssh` | [nitro-install]: https://craftcms.com/docs/nitro/2.x/installation.html "Installation | Craft Nitro Documentation" [craft-install]: https://craftcms.com/docs/3.x/installation.html "Installation | Craft CMS Documentation | 3.x" # Things to know about fast Craft CMS websites Source: https://blog.fortrabbit.com/craft-performance-tuning-debugging Created: 2022-01-16 Author: Frank Lämmer Tags: webdev > What we learned helping clients speed up Craft CMS sites: the backend bottlenecks that come up again and again, and how to measure them. Update 2022-10-28: We have most of the content of this post to our help page [Craft CMS performance tips](https://help.fortrabbit.com/craft-performance). ## What this post is about - backend performance This post is an introduction to backend performance considerations when crafting Craft CMS websites for the wild. This post introduces you to some common PHP related performance bottlenecks with Craft CMS - what happend in the backend. ## What this post is not about - frontend performance We are only looking into issues that are happening before the PHP web server will output any rendered HTML. Usually this is a full page, it can also be fragments of HTML. This is not about any frontend performance tweaking. ## What you want to know about PHP performance ### Time To First Byte and PHP response time For the webserver performance the "PHP response time" is an important metric. It can roughly be translated to the Time To First Byte ([Wikipedia](https://en.wikipedia.org/wiki/Time_to_first_byte)), the latter also includes network latency effects. When running Craft CMS on fortrabbit, with a little tuning and attention to best practices, you should be able to attain a "PHP response time" of 250ms or even less. ### PHP processes and execution time With fortrabbit we are using the FPM (FastCGI Process Manager). Each App get's a limited set of such processes that can run in parallel. A bad example: - Your App has four PHP processes - A PHP request commonly takes one second (long) to execute - A common page view of your website is creating three PHP requests - Each page view is consuming is already occupying most of the available PHP requests - You have three website visitors at the same time - Soon one will have to wait until one of the PHP processes will become free again causing even longer load time You see how this can stack up? That's why it is utterly important to get the PHP response time down. Sometimes clients are asking us in support to increase the `max_execution_time`. While this might help to execute long-running tasks, this also blocks the PHP processes for a longer time. That's we usually advise to lower the time it takes to execute PHP to be able to serve your website to your visitors simultaneously. Our Pro Stack has Workers to offload long-running background tasks. ## How to identify performance problems ### Experience it yourself Your website is slow, you will feel it. Common signs of performance issues are: - Pages are slow to load - the browser loading icon spins - You see timeout errors - a 504 error printed on screen ### Check the hosting metrics The fortrabbit Dashboard offers a metric section (your hosting provider likely will have something similar) including the following vital data points: - **PHP response time**: Aim for less than 250ms on average. In our experience, it's more likely that a website with an average high repsonse time will have problems. Slow websites that are getting some more visits than usual are tending to break down (504) faster. - **5xx error metric**: See if there are any peaks in 5xx errors. If there are, see if at the same time, the PHP response time went up, in that case those 5xx errors are likely 504 time out errors. - **Memory usage**: The memory used should not come to close to the hosting resources you have booked on average, 80% average usage and single peaks are Ok. - **Memory swap usage**: Swap is when there is no (fast) RAM available anymore and data needs to be accessed from disc (slow). This should be within bounds, which depends on your website. - **OpCache**: This should not max out. Aim for 80% or less. ### Use load testing We advise to put your website under some controlled stress to see when it will break. There are tools you can use from your computer to fire up a couple of simultaneous requests. This way you can see how the website will behave before your first unlucky visitors will find the bottleneck for you. ### Profile your Twig templates The YII toolbar is integrated with Craft CMS. It's easy to use and can help you to find slow queries with low efforts while developing. - [Yii debug toolbar documentation](https://www.yiiframework.com/extension/yii-debug-toolbar) ### Use external profilers There are also commercial, professional profiling services providing helpful detailed low-level profiling information. They can be useful for bigger projects with some more traffic. On the server side, they are integrated as PHP extensions (pre-installed on fortrabbit). The most popular ones are Blackfire (recommended by us) and NewRelic. - [fortrabbit NewRelic help](https://help.fortrabbit.com/new-relic) - [fortrabbit Blackfire help](https://help.fortrabbit.com/blackfire) ## Kind of issues ### MySQL related issues **Understand how Craft CMS makes use of the database** The beauty about Craft CMS is that you can get by with just writing TWIG templates — you don't need to write a single MySQL query yourself. Within the TWIG templates there is an abstraction layer to create a query to the database. That's a dangerous tool at your proposal since there a couple of important not so well known things about it. - Craft is running database queries all the time, completely blocking - Craft is joining all the time, since everything is an element, that can get slow quickly There is much more to know, exceeding the scope of this post. Here are the most important parts: **Understand that the MySQL dataset size matters** The flexible content model in Craft CMS makes it easy to write code that makes either too many database queries and/or slow queries in MySQL. Most commonly poorly performing MySQL queries are easy to miss during development, since with local development you commonly **only have a small dummy dataset**. Also mind your local machine has a different hardware than your hosted website. In production later on, when all the pages are published and a couple of blog posts have been written, the underlying issues will become more visible. MySQL query runtime is not just adding up, it's multiplying. **General tips on MySQL performance with Craft CMS** **Prevention is better than cure!** If you're reading this, the odds are you may already have run into performance issues on a Craft CMS project. But if you're just starting out with a new project, being aware of how Craft models content behind the scenes can spare you a lot of time-consuming debugging later on. Look out for code smell: Common Craft performance anti-patterns include: - `where` conditions on custom fields - Queries in nested loops (N+1) - Order on custom fields `orderBy` Please also see our [fortrabbit general help on MySQL debugging](https://help.fortrabbit.com/mysql-performance). **Optimizing database queries** - [Official Craft documentation on Eager loading](https://craftcms.com/docs/3.x/dev/eager-loading-elements.html) **Database indexes** - [How does database indexing work? on StackOverflow](https://stackoverflow.com/questions/1108/how-does-database-indexing-work) - [What columns are indexed in Craft (source code link)](https://github.com/craftcms/cms/blob/d4be41dae683f1f06d42c300620b556c9c057ad3/src/migrations/Install.php#L754-L935) ### Issues related to blocking PHP requests Like described above, a PHP process is busy as long as it is executing. No one will pick up the phone (return a web page) when all the PHP processes are busy. There are various reasons why PHP requests are busy or are running for too long. Examples from support: - A plugin is querying an external service in a blocking way and the answer is taking too long - The database is overwhelmed by too many or too expensive queries ### Memory/CPU related issues Sometimes there is just not enough memory or computing power to perform a calculation. This is often the case when image transformations are involved or when a lot of concurrent requests hit your App. Examples from our support: - Image transformations are used extensively to create too many versions of a certain image in too many sizes and formats - Thousands of queue messages need to be processed, often caused by bulk-updates - Bots crawl the entire site including non-existing pages which are not cacheable ### Craft queue related issues Craft has its own queue implementation. You can see and control it from the Craft CMS Control Panel. The [craft-async-queue plugin](https://github.com/ostark/craft-async-queue) helps to improve the performance of the Craft queue. Hanging queues are a bad sign. To see if performance problems are related to the Craft queue, check if one is running and delete it from the Craft Control Panel. This of course is only possible when the website is still responding. Look for errors in the Craft queue. ### Disk I/O related issues Sometimes the file system disk operations are slowing down a website. This can be when your website is accessing the disk a lot. Examples from support: - Using Craft's Twig `{% cache %}` tag missing the key attribute can lead to thousands of cache files with the same data and a terrible cache-hit-rate - The website is configured to write verbose log files ### General configuration related issues Performance problems are also often caused by general misconfiguration. Examples from support: - Not having set the environment to `production` - this can contribute to bad performance since in development mode more things are getting logged - A plugin is (mis)configured to blow up the database ## Fixing and mitigation In our experience, problems are often unique to individual projects. So there is no silver bullet to make things fast. There are however some general things you can do: ### Check and maybe block certain requests Depending on your configuration, checking the source of requests might help you to understand where resources are getting spent. Examples from support: - A deep content structure, creating an endless amount of possible pages that are getting crawled by web crawlers. Block certain bots or rethink your content structure. - Common bot attacks targeting WordPress requesting a `wp-login` page which results in a 404 page, but that page is not cached or creating an expensive database query, so that the requests are generating a lot of load. - The Blitz plugin is configured to flush the cache every hour, which triggers cache warming. [See this Twitter thread](https://twitter.com/o_stark/status/1189626958713368578). ### Caching to the rescue Caching can be highly beneficial, particularly in providing the fastest possible end user experience but shouldn't be a crutch. Instead, it's usually better to find and remediate the **root cause** of the issue where possible. Doing caching wrong can also be the problem itself. You want repeating parts of the website or full pages to be cached and rendered without hitting PHP or a database query touching the server. A "mega menu" is a perfect example and an opportunity for fragment caching. It creates the same database queries (sometimes 50+) for every page. There are multiple approaches for caching in Craft CMS including: - [**Native Twig cache tag**](https://craftcms.com/docs/3.x/dev/tags.html#cache) - the out of the box tool for fragment caching, be careful when using for side effects, more above. - **[Blitz](https://github.com/putyourlightson/craft-blitz)** Craft CMS plugin - a popular full cache plugin with tons of options - **[Upper](https://github.com/ostark/upper)** Craft CMS plugin (by fortrabbit co-founder Oliver Stark) - integrates reverse proxies (Cloudflare, Vanish, KeyCDN) with Craft Please be careful about caching. In our experience, this is probably causing more problems than it is solving. ### Book more hosting resources Of course, we - as our hosting provider - should have an interest in selling you bigger servers, but our experience shows that it usually needs a lot of money to compensate coding and config mistakes and is usually also not a good fix. You can try shopping more PHP memory, better CPU power, and more PHP process. For Craft CMS we recommend at least our current Standard Plan including 256 MB of RAM for PHP. ## Further reading ### Craft Quest videos Ryan has some good educational video content (some paid, some free) on related topics: - [About the Yii debug toolbar](https://mijingo.com/lessons/yii-debug-toolbar-craft-cms/) - [Debugging in Twig and Craft](https://craftquest.io/lessons/debugging-in-twig-and-craft) - [Profiling with Xdebug live stream](https://craftquest.io/livestreams/profiling-in-xdebug) - [Debugging with Xdebug course](https://craftquest.io/courses/debugging-with-xdebug) ### BONUS: How to work effectively when debugging performance - Make a Git branch for your refactoring and commit as you go - use the history to record your investigations as you go, and so you can step back if you make a mistake - Isolate the parts of your templates that run queries in turn (search/grep for `craft.entries` / `craft.categories` etc) to find candidates for the poorly performing parts - Change one thing at a time - For new problems, use `git bisect` to find where problems were introduced into your project - Look out for common anti-patterns ## Related Craft CMS reading - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — what to know before upgrading. - [Testing Craft CMS sites with Pest](/craft-cms-pestphp-testing) — unit tests for your templates and modules. - [Frontend testing for Craft CMS](/craft-cms-frontend-testing-with-codeception-and-cypress) — end-to-end with Codeception and Cypress. - [User account management with Craft CMS](/craft-cms-user-account-management) — custom login and account templates. - [Image processing in Craft CMS with the Image Toolbox plugin](/craft-image-transform-toolbox) — responsive images and WebP variants. - [3 ways to reset the Craft CMS control panel password](/three-ways-to-reset-the-craft-cms-control-panel-password-without-email-access) — admin recovery without email. - [Craft CMS CVE 2025-32432](/craft-cms-cve-2025-32432) — high-impact RCE vulnerability and what to check. - [Craft CMS CVE-2023-41892](/craft-cms-cve-2023-41892) — earlier vulnerability that prompted a wave of attacks. ## Thanks - You for scrolling or reading such a long article. - [Tom Davies](http://tomdavies.net/) for contributing to this article, especially the MySQL related parts. --- - [Craft CMS guides](/guides/craft-cms) # Custom HTTP Error Pages (Sneek Peek) Source: https://blog.fortrabbit.com/custom-http-error-pages Created: 2012-07-26 Author: Frank Lämmer Tags: webdev > A sneak peek at the handmade fortrabbit error pages, built to be useful in the moment something on a hosted site goes wrong. Putting the pieces together: our PHP platform is shaping. We are currently running lot's of tests and we are looking forward to start the private BETA soon. But there always should be some time for details. Have a look at our custom handmade error pages: [fortrabbit.github.com/Custom-HTTP-Error-Pages](http://fortrabbit.github.com/Custom-HTTP-Error-Pages/) # Damn, we got pwned Source: https://blog.fortrabbit.com/damn-we-got-pwned Created: 2013-05-30 Author: Frank Lämmer Tags: chronicles > In May 2013 the fortrabbit platform was successfully attacked. The full account of what happened, what leaked and what changed after. **Yet another post i hate to write**: Our PHP hosting platform has been successfully attacked last Saturday, the 25th of May 2013. This is our story. On Saturday noon we spotted some irregularities in our dashboard. First, we assumed that the [network issues](/fortrabbit-hiccups-behind-the-scenes) which have been plaguing us for the last weeks were back, but instead we were under attack! Some unauthorized access on an administrative level was going on. Quite scary to see someone moving around in our very private property, without immediately knowing how he got in. Eventually we've identified the loophole and closed it. But damage was already done: sensitive data has been breached (of course NO credit card informations). My first intention was to bury my head in the sand like an ostrich and keep it there until the storm is over. Really, I thought of ignoring what has just happened. But my colleagues quickly convinced me that this is not a good idea. ## A hard choice The next step wasn't easy. Usually we keep our clients Apps online by any means. With a heavy heart we've reseted all database, SFTP and ReSync tool passwords. This took most Apps offline and forced our clients to take action to get the Apps up again. At the same time we informed everybody about the attack. ## Hindsight is easier than foresight When we started our platform we were curious if we will have to face some of the problems our predecessors have been thru. We saw [PHPfog being taken over](http://blog.phpfog.com/2011/03/22/how-we-got-owned-by-a-few-teenagers-and-why-it-will-never-happen-again/). Surely we would do better, wouldn't we? We have been around for some while. We saw some things and we take security actually very serious. We were shocked, when we learned how the attackers came in. Too easy! We thought of CSRF, XSS and SQL injections, but forgot about the cellar door. And yet that was not our only mistake: We got pnwed with our own tools. Once inside the rabbit hole they could move much too freely. > It's always a combination of small mistakes culminating to a big problem! _Somehow we even deserved this - but not our clients._ In retrospect we ponder what led to this. Maybe our "lean thinking" has something to do with all this? Instead of iterating endlessly to the perfect product, we shipped. But still our first version was not just a "minimal viable non-starter" - it was a complete service. Since then we [moved quickly](http://fortrabbit.com/changelog) \- maybe too quickly? ## Not the end We think in total our approach is the right way to go. But more code review and testing is needed. We have just finished an extensive internal security screening and we are going to have an external screening soon. Alongside we've added further security barriers to limit any possible escalation. We have reseted everything we could, even the lock screen passwords of our mobile phones. ## Moral hang over Of course we can totally understand every customer who turns away now. We claim to back your business and we have failed with this here today. **LOVE**: All the more we are impressed and surprised by the loyalty of our users - just amazing. It makes us think that what we are doing is really needed and that we should go on doing it as best as we can. A million thanks for this! **HATE**: It just seems that the prejudices have been fulfilled. Here is yet another fancy cloud service with trendy developer features - nice to try out, but not useful for production. NO, NO, NO! We are not yet another superficial Berlin hype startup of some twenty something wannabe rock stars. We have really serious intentions here. Again: we are terribly sorry. And again: There is no sufficient excuse we can give you aside from our deepest apology. We would like to promise that we will never make any mistake again in the future, but we can't. To err is human. Our workflows must incorporate this. Let's end this post with a quote by John Ciancutti, Director of Engineering at Facebook (formaly Netflix): > The best way to avoid failure is to fail constantly. # Dashboard improvements Source: https://blog.fortrabbit.com/dashboard-improvements Created: 2016-09-02 Author: Frank Lämmer Tags: changelog > A shorter sign-up, instant login, app access links and a setup guide that extends the trial — the boarding flow rebuilt end to end. ### Quicker sign up * Directly sign up from the homepage * Less form fields to sign up (only e-mail & password) * Instant login with non-blocking double-opt-in * Trial starts immediately after sign up, no extra clicks ### A setup guide to extend the trial * Complete tasks to extend the trial time & experience platform features ### App access infos * The App overview now includes direct code access infos ### As well as * Lesser and updated retention mails * Updated dynamic help pages * Reworded interface texts * Style tweaks ### Up next We're working full power towards the [Hobby line](/sneak-peek). # Deploying code with rsync Source: https://blog.fortrabbit.com/deploying-code-with-rsync Created: 2017-04-03 Author: Ulrich Kautz Tags: webdev > Learn how to use rsync from the command line to deploy code changes (to our Universal Apps) incredibly fast. 2026-03-20: This article is still mostly accurate. Also see our new [help article about rsync](https://docs.fortrabbit.com/dev/how-to/rsync). This article aims to acquaint web developers with the command line tool `rsync`, which is usually available out-of-the-box on any Mac or Linux machine. Using windows, we recommend to run `rsync` from Git bash, which comes with the [official Git release package](https://git-scm.com/downloads). The examples I provide will use WordPress and our [Universal App](https://www.fortrabbit.com/pricing), so there is a focus on PHP developers, but the techniques can be applied to many other hosting environments easily. A note on convention: When talking about the actual command line binary, I'll be using `rsync`. When talking about the tool abstractly, I'll be using just rsync. Also: all `rsync` commands are meant to be executed from your local machine from within your local project directory (=uppermost directory, where your web site or web application is located on your disk), unless explicitly stated otherwise. ## What is rsync? Foremost, it's a synchronization tool. A tool to synchronize files over the network, to be exact. Hence the name rsync, which is a shorthand for **r**emote **sync**hronization. Of course, you can use it also to sync files between folders on your local machine. Either way, it is rather simple to get started and hard to master. Or maybe not hard, but there are a lot of optimization and edge-case options, which you might never, ever need - or maybe you do. As every good open source tool, rsync builds open or connects with other open source software. rsync utilizes the command line SSH client (usually from OpenSSH) as a transport layer to synchronize files to remote machines without any other requirement then having an SSH server available and the `rsync` binary installed. Again: Most Linux installations bring that out-of-the-box, so there is a very good chance that you can use it with about any machine you have SSH access to. Including your Universal App on fortrabbit. ## Why use rsync? In short: It's incredibly fast and has been proven reliable in over 20 years of service. Just to give you some numbers, here two benchmarks on uploading a recent [WordPress](https://wordpress.org/download/) (4.7.2, as of writing this article) via SFTP and via rsync. The unpackaged size is about 25MiB and I am using an uplink with 5Mbit upstream. Also I'll be using a command line SFTP client, so I can do without screenshots. First the SFTP run (upload WordPress recursively): ```bash $ echo 'put -r ./' > sftp.batch $ time sftp -b sftp.batch my-app@deploy.eu2.frbit.com # output of each transfered directory, then: 0.46s user 1.24s system 0% cpu 4:47.38 total ``` That took nearly **5 minutes**. After cleanup of all remote files, now the rsync run: ```bash $ time rsync -av ./ my-app@deploy.eu2.frbit.com: # output of each transfered file, then: 0.23s user 0.11s system 1% cpu 26.804 total ``` As you can see, that only took about **30 seconds**, which is about 10 times faster than the SFTP upload. How come? Well, in essence: SFTP is a file based protocol. This means: it works a bit like HTTP. Each file upload is a single "request", if you will, so all protocol overhead is applied to every transferred file. rsync, on the other hand, doesn't work that way. Simplified: it first builds a local data set (all files which should be transferred) and a remote data set (all files which are already there) and then sends a stream of the missing or changed files from your local machine through SSH "in one operation" to a remote rsync process which then writes it to the disk. So there is no "per file" overhead whats-o-ever, which makes it pretty fast in this case. In a sentence, utilizing the HTTP metaphor: SFTP makes one request per transferred file. rsync makes one request in total. That's just the start. rsync performances becomes really, really impressive once you deal with only file changes in development. ## Getting started Ok, let's dive in with the `rsync` command I used above: ```bash source | v $ rsync -av ./ my-app@deploy.eu2.frbit.com: ^ ^ | | options destination ``` Let me break that down: - **Source**: This is your local source directory. Using `./` means just "the current directory I am in". You could provide an absolute like `/home/my-user/Projects/my-app` or a relative folder like `../my-app` - **Destination**: This is the target URL, where the code should end up. In the example, the URL consists of `@:`. You could also use a local destination, by just providing a folder (see below) - **Options**: Well, those I'll skip for now, cause they merit more explanation. Before going into more detail, let me first show you three additional, simple examples on how to sync two local directories the reverse of the above command and how to sync two remotes: ```bash # synchronize two local folders $ rsync -av ~/Projects/my-app/ ~/Projects/my-app.copy/ # synchronize from remote to local $ rsync -av my-app@deploy.eu2.frbit.com: ./ # synchronize from remote to another remote $ rsync -av my-app-1@deploy.eu2.frbit.com: my-app-2@deploy.eu2.frbit.com: ``` Alright, this should give you an idea on simple it is to synchronize two locations. ### A note on protocols In the above and following examples, I specify an SSH remote, using the schema `@:`. This way, `rsync` will use the `ssh` command line client automatically. rsync comes with it's built-in own "rsync protocol" for remote synchronization, which is more interesting for admins, than developers, so I won't elaborate on it more than that. Just so you have seen it and can identify it: the URL schema for rsync protocl would look like: `rsync://@/`. ### SSH edge-cases Should you need to set specicic SSH options, for example, if you need to provide a specific private key, then you can use the `--rsh` option, which stands for "remote shell" and can be shortend to `-e`. Here an example: ``` # use specific private key $ rsync -av -e 'ssh -i /path/to/your/key' my-app@deploy.eu2.frbit.com:~/ ./ # enforce password authentication $ rsync -av -e 'ssh -o PreferredAuthentications=password' my-app@deploy.eu2.frbit.com:~/ ./ ``` You can add use any `ssh` command line option(s) you want. ## Transferring only changes This is where rsync can play on it's real strengths. Say you have changed ten files in your local code set and want to deploy them now. With SFTP, unless your SFTP client has some kind of synchronization add-on, you would now copy each of those files manually. This can be quite annoying: Searching those files in your SFTP client, transmitting each. Lots of mouse pushing or repetitive command line. It also can be dangerous: Working for a couple of days on a larger patch, than forgetting about a single critical file. Not good. Now, this is where `rsync` comes in. As mentioned before, `rsync` will first build a local set of files and directories and a remote set of files and directories. For each item in either set it will generate a check value. This check value, can be either the timestamp of the last change of a file, the size of a file, the current permissions or even a checksum (think MD5) of the file contents. Or any combination of those. Using the `-a` option (in detail explained below), rsync is gonna use timestamp + file size which is a good balance between performance and accuracy. In short: rsync will detect those ten files you have changed over the days of development by checking their local timestamp and file size against the remote timestamp and file size. Then it will transfer only those changed (or new) files. ### Be safe, make a preview At this point, let me introduce you to the handy `--dry-run` option, which can be shortened to just `-n` which can be merged with our other options to `-avn`: ```bash $ rsync -avn ./ my-app@deploy.eu2.frbit.com:~/ sending incremental file list ./ index.php wp-content/themes/twentyfifteen/404.php wp-content/themes/twentyfifteen/archive.php wp-content/themes/twentyfifteen/content-link.php wp-content/themes/twentyfifteen/content-none.php wp-content/themes/twentyfifteen/header.php wp-content/themes/twentyfifteen/image.php wp-content/themes/twentyfifteen/index.php wp-content/themes/twentyfifteen/page.php sent 39,119 bytes received 196 bytes 11,232.86 bytes/sec total size is 23,325,044 speedup is 593.29 (DRY RUN) ``` Now, running this will print out everything that `rsync` _would_ transfer, as shown above - without doing anything. I recommend to always execute a dry run before actually syncing. Same as missing a critical file, it can be equally bad to transfer a change prematurely. Using dry run, you can at least check whether that would be the case. Once you're sure, that only files which you want to transfer are in the change set, you can just remove the `n` again from the options and execute it normally: ```bash $ rsync -av ./ my-app@deploy.eu2.frbit.com:~/ sending incremental file list ./ index.php wp-content/themes/twentyfifteen/404.php wp-content/themes/twentyfifteen/archive.php wp-content/themes/twentyfifteen/content-link.php wp-content/themes/twentyfifteen/content-none.php wp-content/themes/twentyfifteen/header.php wp-content/themes/twentyfifteen/image.php wp-content/themes/twentyfifteen/index.php wp-content/themes/twentyfifteen/page.php sent 42,771 bytes received 678 bytes 17,379.60 bytes/sec total size is 23,325,044 speedup is 536.84 ``` On the other hand, if you spotted a file which should not be transferred (now or ever), you can: ## Excluding files from synchronization Excluding files is really simple. In essence, you just add `--exclude=path/to/file`. Say we don't want the `404.php` from the previous example to be transferred, you would just do: ```bash rsync -av --exclude wp-content/themes/twentyfifteen/404.php ./ my-app@deploy.eu2.frbit.com:~/ ``` The value of `--exclude` is actually not a file path, but a pattern. This pattern is matched against the files to be transferred. In this case, the following patterns would by synonymous: ```bash # use absolute path, as viewed from the source root $ rsync -av --exclude /wp-content/themes/twentyfifteen/404.php ./ my-app@deploy.eu2.frbit.com:~/ # use partial path $ rsync -av --exclude themes/twentyfifteen/404.php ./ my-app@deploy.eu2.frbit.com:~/ # use smallest possible partial path $ rsync -av --exclude 404.php ./ my-app@deploy.eu2.frbit.com:~/ ``` **Note**: Where you put the initial `/` character is important. `--exclude 404.php` and `--exclude /404.php` are _not_ the same. The former means: Any path, which contains "404.php" is to be excluded. The latter means: Any path, which starts with "/404.php" is to be excluded. ### Advanced exclude patterns That's not all for patterns, you can also use wildcard characters. For example: ``` # (1) $ rsync -av --exclude "*.jpg" --exclude "*.jpeg"` ... # (2) $ rsync -av --exclude "/wp-content/themes/*/404.php" ... # (3) $ rsync -av --exclude "themes/**/*.css" ... ``` Those patterns translate to: 1. exclude all JPEG files 2. exclude all files, which start with `/wp-content/themes`, followed by an arbitrary name (no slashes! so only one level of sub directory!) and ending in `404.php`. So basically: All `404.php` files of all themes. 3. exclude all files, which path name contains `themes/` then followed by anything (including any amount of sub directories) and ending in `.css`. So all `.css` files in all Themes. Also, As you can see, in the JPEG example, you can add any amount of `--exclude` options to the command. ### Remember excludes in a file If you have a set of files which you always want to exclude or you just don't want to add all excludes on the command line, then you can create an file containing all exclusions and then use it via `--exclude-from `: ```bash # add two excludes to a plain text file named "excludes" $ echo 404.php >> .rsyncignore $ echo something-else.php >> .rsyncignore # run rsync, using the excludes file $ rsync -av --exclude-from .rsyncignore ./ my-app@deploy.eu2.frbit.com:~/ ``` The file name `.rsyncignore` I've used here, is just a hint for readers used to working with Git and it's `.gitignore` file, which serves a similar purpose. You can name it however you want, though,. There is still a lot more you can do with exclude, or rather filtering, patterns. Not only is there `--include`, which allows you to finely granulate previous `--exclude` patterns, but there is also `--filter`. I'll leave you to explore what best fits your use-case. Here is a [very interesting blog post by Ira Cooke](http://blog.mudflatsoftware.com/blog/2012/10/31/tricks-with-rsync-filter-rules/), showcasing some edge-case scenarios which might give you a hint at what is possible. ## Dealing with obsolete files Now you know how to synchronize changed and new files to your destination. You also know how to exclude parts of your file set easily. The next thing you probably want to know is how to remove obsolete files. The short answer is: add the option `--delete` to your command line and you are done. To give you and example, using the WordPress setup from before: say you deleted this pesky `404.php` file locally. Now, if you run rsync without the `--delete` option (and no other added or modified files), rsync would tell that it will do nothing: ``` $ rsync -av ./ my-app@deploy.eu2.frbit.com:~/ sending incremental file list wp-content/themes/twentyfifteen/ sent 39,037 bytes received 162 bytes 15,679.60 bytes/sec total size ... ``` Although it marks the folder `wp-content/themes/twentyfifteen/`, as there have been changes (the removal of `404.php`), but no changes which `rsync` is gonna apply. Now, running with the `--delete` option, then the file will be removed from destination. **This is a feature, not a bug**, meaning: rsync won't let you down by deleting files without your say-so. Either way, the first delete run, as always, using the condensed form `-n` of the `--dry-run` option, will show you exactly what would be deleted: ```bash $ rsync -avn --delete ./ my-app@deploy.eu2.frbit.com:~/ sending incremental file list deleting wp-content/themes/twentyfifteen/404.php sent 39,062 bytes received 231 bytes 15,717.20 bytes/sec total size ... ``` After you confirm that `rsync` would only delete, what you want (otherwise: `--exclude` works also to exclude files which are not in your local file set but remote, and you don't want to remove them from remote), you can go ahead and remove the `-n` option and run again. Now, rsync wouldn't be if it would give you not at least four different ways to handle deletes: Besides the `--delete` flag, there is also `--delete-before`, `--delete-after`, `--delete-during` and `--delete-delay` (and `--delete-excluded`, but that's another special case in it's own). Those four variants of `--delete` just let you control when files are remove. This is actually quite handy: When thinking larger amounts of changed files to a live website, you might want to use `--delete-after` instead of `--delete-before`, so that first all new files are in place, then obsolete files are removed, which makes it more likely that your website is not "interrupted", when handling a request during the synchronization, which relies on files which would be removed.. I think you get the gist. ## rsync options In all the above examples, I used `rsync -av ...`. Using those two options is a very good default. Here a detailed explanation what they do: | Option | Description | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `-v` | Verbose. Using `-v` shows all transmitted files an statistical data about the transfer in the output. You can increase verbosity using `-vv` or `-vvv` | | `-a` | Is a shorthand for `--archive`, which is a shorthand for the following set of options: `-rlptgoD` | | `-r` | Means recursive, so all files and directories below the source directory | | `-l` | Tells rsync to keep symbolic links as symbolic links. The alternative would be to resolve them and copy the content the symbolic link is targeting | | `-p` | File (and directory) permissions will be synchronized. So if your local file `foo.sh` is executable, it will be made executable on the destination as well - also use permissions as check criteria | | `-t` | Preserve modification times, which means that the destination modificaton times will be set to the source modification times. Also: Use modification time as comparison check | | `-g` | Set Unix group of file/folder on destination according to group in source. Also: use group as check criteria | | `-o` | Set Unix group of file/folder on destination according to group in source. Also: use group as check criteria | | `-D` | Is a shorthand for `--devices --specials` | | `--devices` | Also synchronize special device files as well. Unless your (remote SSH) user is root - no effect | | `--specials` | Also synchronize socket and fifo files - usually no effect, unless you know what those two file types are and use them | Besides the dry run, remote shell, exclude and delete options, which I've explained above already, here some where handy additional options which you might want to look into: | Option | Description | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `-c` | Instead of modification time and size, use checksum of the file contents. Very precise but not very fast, because it creates a checksum for every file, on source and destination. Use with caution. Useful if modification time on destination is not reliable. | | `-C` | Shorthand for `--cvs-exclude`, which tries to automatically exclude all version control sub folders and files. For example: `.git`, `.hg`, `.svn` and so on. | | `-h` | Make the output human readable, which means: display byte sizes in MiB, GiB instead of plain bytes. | For an exhaustive list of all the possible options and more in depth info on the above options, check out the official [rsync man page](https://linux.die.net/man/1/rsync). ## Further reading - [Manual page of rsync](https://linux.die.net/man/1/rsync) - [How does rsync work](https://rsync.samba.org/how-rsync-works.html) - [Tricks with rsync filters](http://blog.mudflatsoftware.com/blog/2012/10/31/tricks-with-rsync-filter-rules/) # Deploying Laravel on fortrabbit Source: https://blog.fortrabbit.com/deploying-laravel-on-fortrabbit Created: 2025-10-15 10:00:00 Author: Frank Lämmer Tags: webdev > Deploy Laravel to fortrabbit via GitHub — environment variables, build commands, post-deploy migrations, queue workers and zero-downtime swaps. Laravel deployment is a solved problem on most platforms — and yet every host has its own quirks, build timing and limits. This guide is the short version of "how do I deploy a Laravel app to fortrabbit and not regret it later". We cover the path from a fresh repository to a production app with assets and queues. ::CallOut This guide was written with Laravel 13 and Laravel 12 in mind. Have a look at our [updated Laravel guides](https://docs.fortrabbit.com/guides/laravel) too. :: ## Before you begin You need a Laravel application that runs locally, a GitHub account, a fortrabbit account, and the :ContentLink{text="fortrabbit GitHub App" prefix="docs" href="/platform/deployment/github-app"} installed against the repos you want to deploy. The GitHub App is what turns a `git push` to your branch into a deploy on fortrabbit. If you have not connected GitHub yet, install the app, then create a fortrabbit app from the repo. Each branch you connect maps to its own :ContentLink{text="environment" prefix="docs" href="/platform/objects/environment"} — keep `main` for production and add a `develop` environment for staging if you need one. The rest of this post assumes the GitHub App is connected and your repo's main branch is wired to a production environment. ## How fortrabbit handles a Laravel deployment A push to the connected branch on GitHub triggers a deployment on fortrabbit. The deployment service pulls the new commit, runs your build commands (Composer, npm, anything else you configure), runs post-deploy commands, and syncs the result into the environment's storage. The previous build keeps serving traffic until the new one is ready. A few consequences fall out of that: - Anything that needs to persist across deploys must live in `storage/` (Laravel already does this for logs, sessions and cached views by default). - Build-time secrets do not need to be in your repo — they live in the app's environment variables. - The `.env` file you use locally is **not** copied to fortrabbit. Use the dashboard's environment variable editor instead. - Code travels in one direction only: from GitHub to fortrabbit. Files you change via SSH are not pulled back into Git. ## Configure your environment Laravel reads configuration from environment variables via `config/*.php`. On fortrabbit, set these in the :ContentLink{text="ENV vars editor" prefix="dash"} in the dashboard. The :ContentLink{text="environment variables docs" prefix="docs" href="/dev/env-vars/intro"} cover the full lifecycle, including the difference between regular and secret values. The minimum set for a Laravel app: ```env APP_KEY=base64:... APP_ENV=production APP_DEBUG=false APP_URL=https://my-app.eu-1wa.frbit.app LOG_CHANNEL=errorlog SESSION_DRIVER=database CACHE_DRIVER=database QUEUE_CONNECTION=database ``` Generate `APP_KEY` once with `php artisan key:generate --show` locally and paste the result into the dashboard. Do not commit it. Set `APP_URL` to your environment's `frbit.app` hostname for now; switch it to your own domain once DNS is pointed. `LOG_CHANNEL=errorlog` writes Laravel logs to the PHP error log, which fortrabbit collects and surfaces in the dashboard and over SSH. The default `stack` channel writes to `storage/logs/laravel.log`, which works but is harder to follow when you are watching multiple processes. For the database, fortrabbit injects `MYSQL_*` environment variables automatically when the :ContentLink{text="MySQL component" prefix="docs" href="/platform/components/mysql"} is attached. Map them in `config/database.php` rather than copy-pasting credentials. ```php // config/database.php 'mysql' => [ 'host' => env('MYSQL_HOST', '127.0.0.1'), 'port' => env('MYSQL_PORT', '3306'), 'database' => env('MYSQL_DATABASE'), 'username' => env('MYSQL_USER'), 'password' => env('MYSQL_PASSWORD'), // … ], ``` The point of doing it this way: when you scale, swap or add an environment, the credentials change but your code does not. ## Your first Laravel deploy The flow is the same as any other GitHub-based hosting, with one extra step at app creation time: ```bash # locally — initialize the repo and push to GitHub git init git add -A git commit -m "Init" gh repo create --source=. --private --push ``` Then in the fortrabbit dashboard, create a new app, choose the Laravel software preset, and pick the GitHub repo and branch you pushed. The first deploy runs immediately and will be slower than the rest — Composer has no cache to lean on. The build log streams in the dashboard. If your app needs PHP extensions beyond the defaults (Imagick, BCMath, GD …), declare them in `composer.json` under `require`: ```json { "require": { "php": "^8.3", "ext-bcmath": "*", "ext-gd": "*" } } ``` The :ContentLink{text="PHP component docs" prefix="docs" href="/platform/components/php"} list every extension that ships out of the box. ## Build commands The :ContentLink{text="build commands" prefix="docs" href="/platform/deployment/build-commands"} step runs after the deployment service has pulled the latest commit and before the build is synced into the environment. fortrabbit auto-detects `composer install` from `composer.json` and `npm run build` from `package.json` — for most Laravel apps with Vite or Mix, the defaults are correct. If you need to customize, edit them in the dashboard per environment: ```bash composer install --no-dev --prefer-dist --no-interaction --no-ansi --no-progress npm ci npm run build ``` Node.js is available during the build step, so compiling front-end assets happens here — no GitHub Actions or pre-commit build is needed. Built files (Vite's `public/build`, Mix's `public/css` and `public/js`, or wherever your bundler writes) are part of the deploy package and end up in the environment alongside your PHP code. ## Post-deploy commands :ContentLink{text="Post-deploy commands" prefix="docs" href="/platform/deployment/post-deploy-commands"} run after the build is synced into the environment. This is where Laravel's optimization steps belong: caching config, routes and views, and running migrations. Set them in the dashboard under the deployment settings of the environment: ```bash php artisan config:cache php artisan route:cache php artisan view:cache php artisan migrate --force ``` A few notes on this list: - `--force` is required for `migrate` because the deploy environment is non-interactive. Laravel will refuse without it. - `config:cache` reads your `.env` once at build time and freezes it into a compiled file. Any environment variable change after that needs a redeploy or a manual `config:clear`. - `view:cache` and `route:cache` are safe and worthwhile in production — they cut request latency noticeably. If a post-deploy command fails, the deployment is marked failed; the previous build keeps serving traffic. Fix the cause, push again. ## Queues, schedulers and cron jobs Laravel's scheduler expects a single cron entry that calls `schedule:run` every minute. On fortrabbit, set this up via :ContentLink{text="cron jobs" prefix="docs" href="/platform/jobs/crons"} in the dashboard: | Schedule | Command | | ------------ | -------------------------- | | Every minute | `php artisan schedule:run` | For queue workers, fortrabbit supports long-running PHP processes via :ContentLink{text="workers" prefix="docs" href="/platform/jobs/workers"}. Workers are an optional component — book one for your app first, then add a worker with the command: ```bash php artisan queue:work --sleep=3 --tries=3 --max-time=3600 ``` `--max-time=3600` restarts the worker hourly, which keeps memory usage predictable and picks up code changes after a deploy without manual intervention. If you would rather not book a worker, the cron-based fallback works for low-volume queues: ```bash * * * * * php artisan queue:work --stop-when-empty --max-time=55 ``` This processes whatever is in the queue once a minute and exits. Not real-time, but adequate for most transactional emails and webhook fan-out. ## When to reach for GitHub Actions The deployment service handles Composer and Node out of the box. GitHub Actions is still useful when you want something the deployment service does not do for you: - Run your test suite on every push and only deploy if it passes - Lint, type-check or run static analysis as a gate - Build artifacts that depend on tooling fortrabbit's build environment does not include A common pattern: run your CI on `pull_request` and `push`, and let the fortrabbit GitHub App handle the actual deploy when CI passes and the branch updates. The :ContentLink{text="GitHub integration docs" prefix="docs" href="/integrations/git-providers/github"} cover the workflow patterns; our :ContentLink{text="GitHub Actions blog post" prefix="blog" href="/how-to-use-github-actions"} walks through a CI-then-deploy example. ## Zero-downtime deployments The deployment service swaps builds atomically — the previous build serves traffic until the new build is ready, then the switch flips. For most Laravel apps, that is the zero-downtime story. The :ContentLink{text="deployment strategy docs" prefix="docs" href="/platform/deployment/strategy"} go deeper into the merge and replace strategies and what guarantees they offer. The two cases where you can still see brief errors: 1. **Schema-breaking migrations.** A request hitting a model whose underlying column was renamed mid-migration will throw. The fix is a two-step migration: deploy the additive change first (add the new column, write to both), backfill, then deploy the removal of the old column. Laravel's migration files give you the structure for this; your discipline gives you the result. 2. **Cached config drift.** If you change `config/*.php` and ship without running `config:cache` in post-deploy, the live app keeps serving the old cached version until something forces a rebuild. Always include `config:cache` in your post-deploy list. ## Troubleshooting A short list of issues that come up often, and what they mean: **`SQLSTATE[HY000] [2002] Connection refused`** — your app is trying to reach `127.0.0.1:3306` because a fallback in `config/database.php` hardcoded localhost. Fix the config to read from `MYSQL_HOST` with no default, and check that the MySQL component is attached. **Permission denied on `storage/`** — your repo committed files into `storage/` with the wrong permissions, or `storage/logs/laravel.log` exists in git. Add `storage/logs/*` and `storage/framework/{cache,sessions,views}/*` to `.gitignore`, keep only `.gitkeep` files, and redeploy. **Composer runs out of memory** — fortrabbit's build environment has a fixed memory limit. Add `COMPOSER_MEMORY_LIMIT=-1` to your environment variables, or audit your dependency tree with `composer why-not` to find the package pulling in giants. **Asset URLs return 404 after deploy** — Vite's manifest is missing because `npm run build` did not run, or the build output path was overridden. Confirm the build command ran in the deployment log, and that your bundler writes to `public/build`. **`No application encryption key has been specified`** — `APP_KEY` is missing from your environment variables, or `config:cache` ran before it was set. Set the key in the dashboard, then redeploy. These two streams answer 90% of "why is the app behaving this way" questions. ## Related reading - :ContentLink{text="Deploy to fortrabbit with GitHub Actions" prefix="blog" href="/how-to-use-github-actions"} — when CI gating before deploy makes sense. - :ContentLink{text="Deploying code with rsync" prefix="blog" href="/deploying-code-with-rsync"} — alternative transport for cases that do not fit Git deployment. - :ContentLink{text="Composer 2 availability" prefix="blog" href="/composer-2-availability"} — what changed when fortrabbit moved to Composer 2. - :ContentLink{text="Multi-stage deployment for website development" prefix="blog" href="/multi-stage-deployment-for-website-development"} — staging, develop and production patterns. - :ContentLink{text="MySQL JSON column with Laravel" prefix="blog" href="/mysql-json-column-with-laravel"} — schema patterns we use ourselves. For the complete reference, the :ContentLink{text="Laravel guide" prefix="docs" href="/guides/laravel"} covers framework-specific details and edge cases this post does not — including :ContentLink{text="install" prefix="docs" href="/guides/laravel/install"} and :ContentLink{text="deployment" prefix="docs" href="/guides/laravel/deployment"} steps. ## Where to go from here If you have a Laravel app and an empty fortrabbit account, the practical first move is: install the GitHub App, create a fortrabbit app from your repo, set the environment variables above, and push. Most issues surface in the first deploy, and fortrabbit's error messages are direct enough to fix without a support ticket. Once that works, the rest is the same Laravel work you already know — caching strategies, queue tuning, schema design. The platform stays out of the way and gives you predictable deploys for the cost of one `git push`. # E-commerce in 2016 Source: https://blog.fortrabbit.com/ecommerce-status-quo-2016 Created: 2016-01-06 Author: Frank Lämmer Tags: opinion > A look at PHP e-commerce software in 2016, for the developers and entrepreneurs still building custom shops against Amazon. Online retail business is growing. People buy more stuff online. And all of this is occupied by Amazon. Well, not entirely… One small village of indomitable Gauls still holds out against the invador. You, the developers and entrepreneurs building a custom e-shop, are a Gaul. DICLAIMER: There are as many types of e-commerce as stars in the sky. This article is a look at those blinking lights from below with focus on new trends, lightweight and cloud-ready systems. We have a PHP background, which is the language of many E-commerce systems. And we come from Germany which is also home of many projects. ## Categories & trends Some ecommerce solutions are specialized for certain product categories, digital goods, physical products, tickets, coupons, mobile commerce, comparison shopping, all kind of things. Some are made for certain markets and languages. Here are some notable distinguishing features: ### Shopping cart software We'll mostly cover "full e-commerce solutions" for serious business here. To quickly sell some swag from your website you can use a "**shopping cart system**". Those webshops usually come with less features and are easy to use and easy to plug in to any site. ### E-commerce as an CMS Add-On Some eshops are integrated as **add-ons for established CMS**. The Drupal space is mostly ruled by [Drupal Commerce](https://drupalcommerce.org/); for WordPress we have: [WooCommerce](https://www.woothemes.com/woocommerce/), [WordPress eCommerce](https://wpecommerce.org/), [MarketPress](https://marketpress.com/), [Cart66](http://cart66.com/) and many many more as you can guess. ### E-commerce & frameworks Modern PHP frameworks are based on Composer. You'll find some commerce components on packagist, mostly for specific tasks (payment, billing, cart-solutions …). The **[Sonata project](https://www.sonata-project.org/)** is a set of bundles based on Symfony2. [Lavender](https://github.com/lavender/lavender) (not much going on) is an e-commerce framework built on top of Laravel. [Aimeos](https://aimeos.org/) provides ecommerce bundles for Typo3, Typo3 Flow, Symfony2 and Laravel. ### Hosted e-commerce Most online stores shown here are classical self-hosted e-commerce systems — these are of course more interesting for us as a hosting provider. But of course there are: **Hosted e-commerce solutions** — Commerce as a Service (CaaS). For example: [Shopify](https://www.shopify.com/), [Bigcommerce](https://www.bigcommerce.com/), [Volusion](http://www.volusion.com/), [Big Cartel](https://www.bigcartel.com/), [3dcart](http://www.3dcart.com/), [Kong](https://trykong.com/), [Squarespace commerce](http://www.squarespace.com/commerce/). Some hosted ecommerce solutions are made for micro-businesses (shopping carts) — where "no coding skills are required". But they are not limited to that: Shopify for instance has it's own template language: Liquid which gives you much freedom about the frontend. ### E-commerce by API **API is the new black**: Salvo Zappalà outlined concepts for API driven e-sales in his post about [building next-gen ecommerce](https://medium.com/@salvoadriano/building-the-next-generation-ecommerce-26093f98d2d7) — imagining the e-commerce system as the "back-end" as part of an Service Oriented Architecture. Front-ends are a web client, mobile apps and an admin panel. That also blurs the boundaries between programming languages. The Drupal Commerce Guys are going in that direction, Sylius and Sellvana as well. And there are already some startups out there. Those are mostly closed source and hosted: - [Schema.io](https://schema.io/) API first and only - [Moltin](https://moltin.com/) hosted + API - [Mozu](https://www.mozu.com/) hosted + API, brainchild from Volusion, US - [commercetools](http://www.commercetools.com/) (ex sphere.io) from DE, Berlin ### Licensing You can have a professional e-commerce system for literary free. Or you can pay LOT'S of money for a license. This can even happen to be for the same software. And it all makes sense. E-commerce is undeniable a space where money is involved, nobody creates an e-commerce software to make the world a better place. That doesn't mean that all software is closed source. You can find interesting open source business models here as well: additions costs extra, commercial support, professional license + community edition … ## Rookie e-commerce software We are mostly interested in those newcomers here of course. Composer packages are making it easier to develop ecommerce solution as a lot of basic stuff is already been taking care of. So naturally there is a new generation of e-commerce: **[Craft commerce](https://craftcommerce.com/)** has a brother: Craft is a PHP CMS system with a good reputation. The maintainers Pixel & Tonic have recently released version 2.5, along with the new Craft commerce — an e-commerce solution based on Craft. It looks quite modern. A license currently costs $999. **[Sylius](http://sylius.org/)** from Paweł Jędrzejewski (Poland) is still under development and looks promising. ~2k GitHub stars **[Sellvana](https://www.sellvana.com/)** is an upcoming ecommerce solution by [unirgy](https://twitter.com/unirgy) and others. 5 GitHub stars **[Elcodi](http://elcodi.io/)** Symfony components, Composer — keep talking. This is Elcodi from Barcelona, another young promising candidate. ~390 GitHub stars **[Thelia](http://thelia.net/)** (still in version 2) from France is an ecommerce based on Symfony2 components with Smarty 3 templating engine. ~550 GitHub stars **[Mothership](http://mothership.ec/)** is another newcomer that promises to combine e-commerce with a point of sale (ePOS) solution. ~15 GitHub stars **[Arastta](https://arastta.org/)** (from the comments below) is yet another newcomer. The core team behind it is Miwisoft which comes from Istanbul. Ararstta is based on Symfony components and also follows the API approach. There is a free open source edition and a hosted one. Version 1.2.1. was released in December 2015. ~100 GitHub stars **[Yo!Kart](http://www.yo-kart.com/)** (also comments) is rooted in India (I dig this). It's available as a hosted and a self-hosted version, it's not really open-source. ## Veteran e-commerce software Old does not have to be rusty. It also means means tried and tested, feature complete and maybe even in a new version: **[Magento](https://magento.com/)**, started in 2008, is the elePHPant in the room. Everything is covered: there is a community edition and a enterprise edition. It's a huge eco-system with modules (extensions), themes and an active community around it. Many digital agencies are specialized solely in Magento. The second major version was expected for 2011, but it took a bit longer. Magento 2.0 was finally released in December 2015. ~3k GitHub stars **[Prestashop](https://www.prestashop.com/)** started in 2005, is from France and shall [soon](https://github.com/PrestaShop/PrestaShop/blob/develop/composer.json) be based on Symfony components. ~1.5k GitHub stars **[Shopware](https://en.shopware.com)** has been around since 2004 and is still [looking sexy](https://github.com/shopware/shopware/blob/5.1/composer.json). It was born in Schöppingen in Münsterland. There is a free community edition as well as professional and enterprise ones. ~350 GitHub stars **[Spryker](https://spryker.com/)** is a high-end solution. Developed inhouse as "Alice & Bob" by Rocket Internet and later by Project A as "Yves & Zed". A license will cost at least €100K, but you won't find prices on the website. **[Pimcore](https://www.pimcore.org/en/product/multi-channel-e-commerce-platform)** is also rooted in the enterprise sector and does it all. It's a CMS that has an integrated multi-channel e-commerce platform (Enterprise Add-On). ~500 GitHub stars **[Reaction Commerce](https://reactioncommerce.com/)** is an open source JavaScript (build on Meteor) for ecommerce, currently in beta. ~1.7k GitHub stars **[Spreecommerce](https://spreecommerce.com/)** is probably the most notable e-commerce system written in Ruby. ~7k GitHub stars — But i learned (see below) that it is no longer maintained and succeeded by [Solidus](http://solidus.io/). **[OXID Esales](https://www.oxid-esales.com/en/home.html)** is yet another bedrock from Germany. ### Even more The list should goes on: [Lemonstand](https://lemonstand.com/), [osCommerce](https://www.oscommerce.com/), [OpenCart](http://www.opencart.com/) (don't use it, [pushad claimed](https://www.reddit.com/r/PHP/comments/2tu3x5/whats_the_best_php_ecommerce_platform_to_get_into/co2f3ow)), [Avactis](http://www.avactis.com/), [loadedcommerce](http://www.loadedcommerce.com/), [zeuscart](http://zeuscart.com/). A special mention for the most-old-school-looking website goes to [AFCommerce](http://www.AFCommerce.com/). On AngelList you can find [24431 e-commerce startups](https://angel.co/e-commerce). --- ## Finding the best e-commerce software As you might guess: There is no one single best solution. It all depends on your needs and preferred flavor. Find the right mix of customization, **community**, usability, theming, extensibility, hosting-performance, scalability, costs, support, localization features and security yourself. The new solutions are, well: new — sexy, lightweight, developer-friendly, and maybe not as feature rich and hardened. The old solutions are, well, old — monolithic, full-blown, slow, lame, but functional after all. ### An opinionated word on hosting If you are planning to start an ecommerce project based on PHP, check out our platform here, it's fast, reliable and we really care about PHP.

Image credit: For the illustration I made use of Multi Cart Pile-Up photo by Gayle Nicholson via Flickr

# Essential metrics are here Source: https://blog.fortrabbit.com/essential-metrics-are-here Created: 2026-02-03 15:26:54 Author: Frank Lämmer Tags: changelog > Usage metrics land in the fortrabbit dashboard: MySQL storage, web storage and monthly traffic, shown per environment as they update. ## What's new? The environment overview of the dashboard now shows usage data for components that report usage: - MySQL - database storage used, now - Traffic - outbound traffic, so far this month - Storage - sum of all files on the file system, now You can see the current state and update component plans accordingly. Usage is also plotted alongside the component booking for reference. With this update, actual usage is compared against the plan. ![Essential metrics demo](/images/essential-metrics.gif) This is the first iteration in a series of updates about metrics. ## Current limits The current implementation provides a snapshot of usage; there is no historical data available yet. The latest state gets pulled every minute. ### Live dashboard updates Some customers noticed that not all updates are pushed into the browser within the dashboard SPA. For the important parts, we have implemented polling. The goal is to have server-side events with live updates pushed into the dashboard. That is a larger development project and will improve the dashboard experience with better observability. This will include infrastructure-related events, but also dashboard events like collaboration. ### Detailed metrics ![Metrics demo](/images/metrics-mockup.png) The above image is an early prototype. It will look better later on. Another ambitious project is to show server-side generated metrics. Users of the old platform may have noticed that common metrics are still missing in the new platform. PHP response time, CPU allocation, requests, and many other server metrics are not shown yet. We already have most parts of the backend ready, but we cannot show that yet in the dashboard. The metrics for the new platform will build on what we have learned over the past decade with the old platform. It will help in two ways: - Performance insights - not replacing :ContentLink{text="APM services" href="/integrations/apm/intro" prefix="docs"}, but already good - Usage data - not replacing :ContentLink{text="Web analytics" href="/integrations/web-analytics/intro" prefix="docs"}, but already good Metrics will include plotted graphs over time. With the live update features described above, new metrics will be pushed into the browser. ### Logs We also plan to bring log access directly into the dashboard. With live updates, users can tail and filter logs by time range and type. ## Thanks It is an honor for us to work with our helpful beta testers. Feedback so far is very good. The beta is paid, but we are happy to apply a discount for feedback, ideas, and use cases. --- - [New platform beta program](/platform/new/beta) # My favorite Facebook bot designs Source: https://blog.fortrabbit.com/favorite-facebook-bot-designs Created: 2018-01-08 Author: Frank Lämmer Tags: chronicles > A collection of Facebook reaction bots found on hosted sites, and the accidental brutalist beauty of their interfaces. So: A Facebook reaction bot will automatically like Facebook posts. I assume that this is used for farming business or maybe just to artificially boost someones reputation. We see some manually created WordPress based bots from time to time here. I think most are based on step by step [video instructions](https://www.youtube.com/watch?v=Bi3sLwnSncM). I admit to feel some sympathy for this. And I also like the designs in a way. They remind me of old [demoscene](https://en.wikipedia.org/wiki/Demoscene) crack intros and they also perfectly align with a modern [brutalistic web design](http://brutalistwebsites.com/) trend. Also one can sense the authors age, interests and cultural background. ## Gallery ![Facebook bot screenshot](/images/facebook-bot-1-s.png) ![Facebook bot screenshot](/images/facebook-bot-2-s.png) ![Facebook bot screenshot](/images/facebook-bot-3-s.png) ![Facebook bot screenshot](/images/facebook-bot-5-s.png) ![Facebook bot screenshot](/images/facebook-bot-6-s.png) ![Facebook bot screenshot](/images/facebook-bot-7-s.png) ![Facebook bot screenshot](/images/facebook-bot-8-s.png) ![Facebook bot screenshot](/images/facebook-bot-9-s.png) ![Facebook bot screenshot](/images/facebook-bot-14-s.png) ![Facebook bot screenshot](/images/facebook-bot-15-s.png) ![Facebook bot screenshot](/images/facebook-bot-16-s.png) ## Disclaimer Please mind that using fortrabbit in this way is against our terms and also very likely against Facebook terms. We'll continue to block and delete any such attempts and we also reserve the rights to take further (legal) steps on this matter. This post is only the design aesthetics. I totally respect hacking culture. It's not intended to harm or make fun of the creators. Some possibly personal data has therefore been blurred. ![](/images/facebook-bot-support.png) # File-based CMS overview Source: https://blog.fortrabbit.com/file-based-cms-2016 Created: 2016-06-07 Author: Frank Lämmer Tags: opinion > Thoughts on flat file CMS and static site generators, mostly PHP-related. ### Manifesto - Skip the database - Dump the rich-text WYSIWYG editor - Write text files in Markdown - Store meta data in the text file as a front matter YML block - Use Git (and Composer) to manage and deploy ### Scope A **developer-friendly** Content Management Systems for: blogs, simple websites, themes, components, docs, gh-pages, prototypes, click-throughs … you name it. I'd like to split those systems in two different flavors: ## Static site generators A static site generator will parse all your contents to build plain HTML pages out of it. For a blog it will turn the Markdown source files to HTML using templates and also generate archive lists. **It's a radical concept after more then 20 years of server-side scripting.** The HTML files can be generated on your local machine and then deployed to any web server that can render HTML, no PHP, Ruby or Node required. Let's fight [website obesity](http://idlewords.com/talks/website_obesity.htm): Simple HTML pages can of course be rendered faster using less computing resources. As a static site generator is actually a task runner, it can be build with anything — Gulp for example. And it can also compile to anything — the output format can also be an e-book. ### Example candidates [Jekyll](https://jekyllrb.com/) is the most known candidate - it's integrated in GitHub (GitHub pages). But there are many more: [StaticGen.com](https://www.staticgen.com/) lists 143 different systems. [Sculpin](https://sculpin.io/), [Couscous](http://couscous.io/), [Spress](http://spress.yosymfony.com/) are in PHP. ### My experience We have used [Metalsmith here for a while](https://blog.fortrabbit.com/new-blog-layout) but eventually ditched it. Each build process generated 100 of HTML pages. It was fast, but still an extra step. ### Deployment & hosting At minimum you want the exported folder uploaded and served somewhere. #### Static site hosting - use GitHub pages for this and route your domain there (free) - setup a task that deploys all files to an AWS S3 bucket and route your domain there (cheap) - store those files in Dropbox folder and route the domain (free i think) Please consider that you want to have the source code that creates the files as well as the original markdown files backed up. With the GitHub pages way this is solved (master branch contains source, gh-pages the generated stuff), Dropbox has it's own backup-magic, for the AWS way you might find something else. #### With fortrabbit 1. pragmatic: put everything in Git and deploy it all together, route your domain to the output folder 2. clean: define the built process to run as a post-deploy script, after each deploy (of course only when using a PHP generator) --- ## Flat file CMS **Flat file CMS are static site generators without the static part.** Rendering is done dynamically — using server-side scripts. Each time a user requests a certain resource, a HTML page will be built: combing templates and the actual contents from the Markdown files. Still no database: all reads are done from the local file system. Of course this requires some more computing power from the web server and thus can not be as fast as delivering raw HTML pages as with the pre-generated sites. But clever caching can help to deliver even complicated queries fast — humans will not spot the difference. So: still the same look and feel, but without that tedious built process. ### Candidates | Name | Established | License | GitHub Stars | Twitter | | -------------------------------------- | ----------- | ------- | ------------ | ------- | | [Baun](http://bauncms.com/) | 2015 | 0 | 200 | | | [Bludit](https://www.bludit.com/) | 2015 | 0 | 120 | | | [Grav](https://getgrav.org/) | 2014 | 0 | 4300 | 2900 | | [Herbie](https://www.getherbie.org/) | 2014 | 0 | 30 | | | [HTMLy](https://www.htmly.com/) | 2014 | 0 | 430 | 6 | | [Kirby](https://getkirby.com/) | 2009 | $15 | | 4000 | | [Monstra](http://monstra.org/) | 2012 | 0 | | 400 | | [Phile CMS](http://philecms.com/) | 2013 | 0 | 200 | | | [Pico CMS](http://picocms.org/) | 2013 | 0 | 2000 | 20 | | [Pulse](https://www.pulsecms.com/) | 2015 | $39 | | 500 | | [Sphido](https://www.sphido.org/) | 2014 | 0 | 160 | | | [Stacey](http://staceyapp.com/) | 2009 | 0 | 1000 | | | [Statamic](https://statamic.com/) | 2012 | $200 | | 2600 | | [Yellow](http://datenstrom.se/yellow/) | 2013 | 0 | 200 | | There are many more, but these well known (in PHP) and actively maintained. ### My experience I did a small project in Grav and liked it. Grav is still a bit rough around the edges and feels like an Open Source project here an there — but that's exactly what it is. The good documentation, the demo templates, plugins and the community helped me getting up fast. We also use custom flat file generation for this blog and our [help pages](https://help.fortrabbit.com) using some custom micro scripts based on [Slim](http://www.slimframework.com/). So I probably would prefer a flat file CMS over a static site generator for these kind of tasks and when being with other developers. We work with Git subtrees to separate code from content. The content of our documentation is a [public repo hosted on GitHub](https://github.com/fortrabbit/help). We pull this into an App to generate the layouts. But that doesn't help with the admin-dashboard case. ### Deployment & hosting Some **flat file CMS** are providing browser-based wordpress-like admin panels. And I totally get why: The "client" should be able to use it as well. That changes deployment & hosting a lot: #### With fortrabbit Files created on the server are breaking compatibility with our hosting service and most other PaaS. Our New Apps have [ephemeral storage](https://help.fortrabbit.com/quirks#toc-ephemeral-storage). Any file manipulation on a remote server will be lost on each new deploy or change of settings and is only done on one Node, where the App can run on multiple Nodes (horizontally scaled). The immediate reflex is to think: Hey, let's store those Markdown texts in a database! Isn't it better to separate the code from the contents anyways? Well, maybe. But then it's not file-based anymore, that's just a regular CMS. **Other possible hacks** - save `*.md` files to a remote file system (S3 or [Object Storage](https://help.fortrabbit.com/object-storage) in our case); - commit changes from the admin panel to Git again so that new contents can be pulled. **Bottom line**: You can't really host a flat file CMS in a 12-factor environment: when new contents get generated on the server (client mode). But you can perfectly host it here: when you skip the admin-dashboard and content & code live together in a repo and you deploy it all together (dev style). #### With classical hosting > Code moves up. Content moves down. In a classical hosting scenario you might have the following setup: The newest source code comes from your local machine, to update the server you upload the changed files manually, or use Git and then ignore the folders containing the actual contents. Then you possibly need to find a way to move the latest content down to your local development environment (as a backup and to have the local dev close to production) — or you just rely on the backups your hosting partner provides. Bottom line: A flat file CMS can be hosted in a classical hosting environment, but you need a good strategy to merge content and code together. ## Wrapping up **Separation of presentation and content** is something file-based CMS are not about in the first case. The beauty of those systems is the pragmatic **get-the-job-done-quickly**-without-too-much extras-and-tech-evolved approach. Old-school CMS like WordPress are doing a better job in separation, as the content is (mostly expect for uploads which hasn't been covered here at all and is a topic of it's own) in the database. Markdown text files on disk — on the other hand — are very accessible, they make sense even alone without the presentation layer. ## Headless CMS to the rescue? ![Headless animated GIF](/images/headless.gif) Let's see what an upcoming wave of decoupled, api-based CMS will bring us. I want these three layers: - **Engine**: back-end makes an API available - **Content**: Data in a portable format - **Presentation**: Front-end templates and styles # Introducing FindHost, a register of hosting providers Source: https://blog.fortrabbit.com/findhost-a-register-of-web-hosts Created: 2026-08-21 Author: Frank Lämmer Tags: opinion, chronicles > I have built an openly-licensed, ratings-free register of web hosting providers. Why? Check out **[findhost.app](https://www.findhost.app)** — a data-driven register of web hosting providers, a marketing vehicle that is hopefully valuable. ## The trouble with researching a web host Search for a web hosting provider today. You will get all the "best of 2026" lists, and every link carries an affiliate tag. But vendors without a big marketing budget or another inbound channel are almost invisible. There are smaller, independent hosting providers, like fortrabbit, that provide good and innovative services. They are hard to find. I do most of the 1st level support at fortrabbit, and I am sometimes staggered by how little even good developers know about hosting services. There are many misunderstandings. Most commonly, people assume hosting is a commodity that works the same across all providers, and that the trick is getting the most horsepower per penny. My job at fortrabbit has always been convincing people that service quality and developer experience matter, and that you can do more with less. ## The story of FindHost While preparing for our new platform, I researched the hosting market landscape. That helped us redefine our market position. Later on I turned it into a public web hosting guide on our marketing site. But it felt odd to have that sitting directly under our own brand. The tool would be more useful decoupled from fortrabbit, and extended. The project sat in my backlog for a while. Now, during a holiday trip to France, I plugged out of Slack and found the time to focus on it. ## Looking at the data I read a lot of hosting providers' web pages. Every host now seems to advertise AI hosting. Often it means a GPU you can rent, sometimes it means a chatbot in the control panel, and quite often it means nothing at all. Are we becoming the shitty web? (hm) There are sooooo many hosting providers. A lot of it is still shared hosting. The same product as in 2008, same cPanel, same oversold box, now with SSL. VPS is still everywhere too, some of it still advertising SSD storage. For me, that's mostly noise. The data is not as specific as I would like it to be. The market is fuzzy. Providers looking for a niche sit between the categories, using the same vocabulary to mean very different things. Pricing alone is really hard to compare. Most classical providers are paid upfront, and many lock you in for a year. A lot of shared providers also have renewal multiples — from the second year on it costs two or three times more. ### Featured providers How do I get signal out of this, to push innovative services and small providers? I first tried a scoring system based on a favorable developer experience. I threw it out and made the bias explicit instead. I did put a heart on a handful of providers. That is my biased opinion. ### Discoveries Zerops from Czechia was new to me. I also recorded some defunct providers. Do you know Loudcloud? Essentially AWS before AWS, later Opsware. Or DotCloud, which failed as a PaaS and shipped Docker on the way out. The parallel is a little too neat. Also: Hetzner has a South African branch, called xneelo. ## The build I actually wanted to dogfood Kirby or Statamic, because we need more hands-on hours with both. I ended up with Astro anyway: static output, no database at build or at request time. Astro was new to me. I am still more at home in Vue and Nuxt. The data lives as YAML and markdown in the repository, validated with zod. Each record is one file — fixing a provider means editing that file and opening a pull request. The website runs on fortrabbit, of course. You bet the data is structured, so that AI bots can find and cite it. It has semantic CSS classes, not Tailwind utility class hell. There are actual class names, a couple of stylesheets, and design tokens. It was a breath of fresh air and a bit of a pain to maintain. But OK. AI (Claude) did most of the coding and most of the data aggregation. That is disclosed on the site, per record, in the data. The data is [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). ## Anyway Working on something isolated - no dependencies on the rest of our stack, no coordination - was fun. It is a pet project. It may grow, it may die. There are ideas: reviews, a price signal, local search. For now it is a register. Corrections welcome, on [GitHub](https://github.com/fortrabbit/findhost). # First fortran PaaS Source: https://blog.fortrabbit.com/first-fortran-paas Created: 2014-04-01 Author: Frank Lämmer Tags: opinion > fortrabbit announces the world's first Fortran platform as a service, with a new stack and full support. Published 1 April 2014. Hold on tight. Something big is here! Today, we're very excited to announce: support for the [fortran](http://en.wikipedia.org/wiki/Fortran) programming language — right here, right now. ### Why Fortran? It's not only that **fortra**bbit and **Fortra**n share the same first six letters — there is much more! First, let's make something clear: this horse called PHP you are riding is dead. Get off. And [90ies subculture music](http://hhvm.com/) won't save it. But what to do? Join the mustache movement shouting "JAVASCRIPT ALL THE THINGS!"? No. Mainstream is boring. Let's find a blue ocean — a market yet small but with huge growth potential — one we can attack aggressively with our disruptive strategy. We are first in class for Fortran cloud hosting. ### Fortran is very fast [Fortran is faster than C++](http://stackoverflow.com/questions/13078736/fortran-vs-c-does-fortran-still-hold-any-advantage-in-numerical-analysis-thes). We've been [researching](http://flibs.sourceforge.net/fortran-fastcgi-nginx.html) and running all kind of benchmarks. Let me just tell you: it's crazy fast. ![fortran-benchmark](/images/fortran-benchmark.gif) ### Fortran is very secure Stop worrying about loopholes, zero day exploits and backdoors. Printed punch cards can't be hacked. ### Fortran is very stable This is not a bunch of Perl scripts hacked together for Pretty Home Pages. This is an industry standard, originally developed by IBM in 1957 — tried and tested — in use for weather forecasting, aeronautics, aerospace, and the military. ### What you need to know now From today on, all new Apps on fortrabbit will run on the new fortran language stack. By tomorrow, the 2nd April 2014 we will switch all existing PHP Apps on fortrabbit to fortran (77 standard straight). **Please rewrite all of your code today.** # A first look at the new Craft Nitro development tool Source: https://blog.fortrabbit.com/first-look-craft-nitro-development-tool Created: 2020-10-14 Author: Jascha Silbermann Tags: webdev > A first look at Craft Nitro, the local development tool by Pixel and Tonic, measured against DDEV for running a Craft CMS site. Previously, we explored a variety of dev tools in our [article on local PHP development](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup). We narrowed our focus to [setting up a Craft CMS site with the DDEV development tool](https://blog.fortrabbit.com/local-craft-dev-site-ddev-development-tool). Here, we examine if the new Craft Nitro local dev tool will also fit our purpose. DISCLAIMER: this article reflects the author's opinions and is based on their experience testing Craft Nitro on macOS while adhering to common best practices. ## An overview of the Craft Nitro development tool Nitro caught our attention during a recent [devMode.fm Podcast](https://devmode.fm/episodes/boost-your-local-development-with-nitro) dedicated to this new development tool. The [introductory blog post](https://craftcms.com/blog/craft-nitro) on the Craft CMS homepage states that: > “Nitro is a speedy new local development environment that's tuned for Craft CMS, powered by Multipass.” So, what does this mean? First of all, **Nitro is a command line tool.** **It consist of a single executable** installed to `/usr/local/bin/`. To achieve this level of simplicity, Nitro uses a local virtual machine (VM) based on Canonical's “Multipass” Ubuntu virtualization technology. Nitro strives to make local development easy and deliver high performance for local Craft dev sites. Additionally, Nitro tries to **balance ease of use with the ability to customize it**. In the words of one of the Nitro developers comparing Nitro to other dev tools: > “Every solution sucks in its own unique way — Nitro tries to be the one that sucks the least” From the devMode.fm Podcast episode we learned that Pixel & Tonic, the company behind Craft CMS, are pushing towards a Laravel-like ecosystem, with best practices in place for common use cases. From the perspective of the Pixel & Tonic team, a **large percentage of Craft support requests are related to both local development** and production config. For less technically-inclined users, getting something like [Homestead](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup#homestead) up and running can be a challenging process. With Craft Nitro, Pixel & Tonic hope to level the playing field for new Craft developers. ### Craft Nitro Features We previously discussed [best practices for setting up a local dev site](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup#local-dev-site-setup). Most solutions offer a way to script and automate the setup process of a local development environment. With VM-based tools, this process is known as “provisioning” and consists of two components: the provisioning software, and a user-editable configuration file. For Craft Nitro, the environment **configuration is held in a YAML file that adheres to the “Cloud Init”** industry standard. Broadly speaking, most local dev tools fall into one of two categories: those based on a virtual machine, and those based on Docker containers. Craft Nitro employs a hybrid approach: it uses a **virtualized Ubuntu instance, but additionally runs Docker inside the VM**. This allows Nitro to work with and seamlessly switch between different database versions, as each version runs in its own Docker container. Like other popular dev tools, Craft Nitro is controlled via the command line. It offers a [host of useful commands](https://craftcms.com/docs/nitro/commands.html), such as `db backup` and `db import`, to backup and restore a database snapshot, respectively. A single instance of Craft Nitro **can be used to power multiple Craft sites**, and there's also a convenient option to host an entire folder of existing Craft CMS projects. In the future, Craft Nitro might get a graphical user interface (GUI), making it even more accessible for developers and designers looking to quickly set up a local Craft site. As previously mentioned, Craft Nitro runs on top of the Multipass virtualization technology. This innovative piece of software is made by Canonical, the company behind the popular “Ubuntu” Linux distribution. **Multipass uses the operating system's native hypervisor**, which promises a significant performance boost when compared with non-optimized virtualization tools. ### Installing the Multipass virtualization technology on our local machine On a Mac, **Multipass can be installed with a single [Homebrew](https://brew.sh/) command**: ```bash brew cask install multipass ``` The same should work on a Linux system, for which [Homebrew is also available](https://docs.brew.sh/Homebrew-on-Linux). For other operating systems, or if Homebrew is not available, the **installation may be carried out using one of the installers provided** on the Multipass homepepage: - [multipass.run](https://multipass.run) We first **attempted to install Multipass on a Mac using Homebrew**, but quickly ran into a Multipass permissions error: ``` multipass socket access denied Please check that you have read/write permissions to '/var/run/multipass_socket' ``` For context, we adhere to the **best practice of operating a main user account without admin privileges**, with a separate privileged user account set aside for administrative tasks. With this setup, software can normally be installed via the Homebrew package manager when logged in as the admin user. Once installed, the software can be used by a non-admin user as well. Unfortunately, this does not appear to be the case with Multipass. Since our Homebrew installation attempt was unsuccessful, we tried the installation again, this time using the package installer from the Multipass homepage. Unfortunately, **we got the same permissions error when starting Multipass**. To work around the "multipass socket access denied" permissions error thrown by Multipass, we used the following code: ``` # For this to work on macOS there must be two user accounts: # # non-admin user: # admin user: # # start session as non-admin user # and save user name for later user=$(whoami); export user # edit your admin user name below admin="" # log in as admin user — will ask for your admin password su "$admin" # add non-admin user to group `wheel` # sudo commands may ask for your admin password sudo dseditgroup -o edit -a "$user" -t user wheel # change group ownership of multipass socket to `wheel` sudo chown :wheel /var/run/multipass_socket # give read-write permissions to `wheel` group members sudo chmod 775 /var/run/multipass_socket ``` Please note that we're changing permissions and group membership, so there may be security implications. **This code is included here for educational purposes only**; use at your own risk. ### Installing and initializing Craft Nitro on our local machine Once Multipass has been installed, **installing Craft Nitro should be a breeze**. All we need to do is open up a terminal, log in as an admin user and run the following commands: ``` # edit your admin user name below admin="" # log in as admin user — will ask for your admin password su "$admin" # under admin account bash <(curl -sLS http://installer.getnitro.sh) ``` This will **download and execute the Craft Nitro installer script**, which will place the `nitro` binary on our system. Then, under a normal user account, we initialize the Craft Nitro machine using the following command: ``` # initialize Craft Nitro machine nitro init ``` Running the command spawns an interactive prompt, which lets us choose the following: - How many **processor cores** to use for the VM. - How many **Gigabytes of RAM** to use for the VM. - The amount of **disk space** allocated to use for the VM. You will need a minimum of 4 GB for the installation. - Which **database engine** to use for the VM. - Finally, which **database version** to use for the VM. Once we've chosen the desired values, Craft Nitro will proceed to download multiple large files. On our first try the **installation failed due to missing packages**. Upon further inspection, we found a bug report stating [“make sure you are not on a VPN”](https://github.com/craftcms/nitro/issues/127#issuecomment-634347495). We switched off the VPN and ran the initialization again. This time it worked and took about ten minutes to complete. ### Adding a local Craft CMS project to Craft Nitro Once the Craft Nitro machine has been set up, we **proceed to adding an existing Craft CMS project**. For this purpose, Craft Nitro provides the convenient `nitro add` command. Running this command inside a Craft CMS project directory will again spawn an interactive prompt: ``` # navigate to Craft CMS project directory cd # add the Craft CMS project to the Nitro machine nitro add ``` During this part of the process we were asked to provide additional details, such as the desired **host name for the site and the webroot directory**. Craft Nitro tries to make this as easy as possible by providing sensible defaults. ### Multipass issues preventing us from using Craft Nitro on macOS Unfortunately, when attempting to add a site to Craft Nitro we again ran into a Multipass permissions issue. At this moment, we felt it was prudent to look a bit deeper into Multipass, as it is the critical software component that Craft Nitro depends on. We discovered that **Multipass has a few serious issues under macOS at the moment**: - On macOS, the [Multipass VM file is stored outside of the normal macOS folder structure](https://github.com/canonical/multipass/issues/566). This is a serious problem, as VM files should normally be stored in a directory that is excluded from Time Machine backups. - The official Craft Nitro documentation states, [“Multipass requires Full Disk Access on macOS”](https://craftcms.com/docs/nitro/usage.html#adding-sites). Again, this seems problematic and is unusual when compared with most other dev tools. - For people running the popular “DNSMasq” tool on their machine, [Multipass can run into DNS issues](https://github.com/craftcms/nitro/issues/127#issuecomment-626239432). DNSMasq is a crucial component of the widely-used dev tool “Laravel Valet” and needs to be stopped in order to run Multipass. Considered together with the aforementioned permissions errors, we concluded that **Multipass is not a viable choice for most use cases on macOS at the moment**. Since Craft Nitro requires Multipass to run, we were unable to complete the setup and failed to use Nitro to power our local Craft CMS dev sites. ## Conclusion Nitro looks really promising, but is hamstrung by the underlying Multipass issues. Maybe on Linux or Windows this works out differently. However, **on macOS the problems seem too much of a hassle to work around** for us. After all, one of the main requirements we have for any dev tool is to [“Isolate the development environment from our physical machine's operating system.”](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup#local-dev-site-setup) Having to set up special permissions, or run the software as an administrative user clearly goes against this basic rule. That being said, do keep an eye out! **If Multipass matures Craft Nitro might still be a great choice** for local Craft CMS development. For the time being, [we recommend to use DDEV instead](https://blog.fortrabbit.com/local-craft-dev-site-ddev-development-tool). It's a great tool that runs on top of Docker and doesn't suffer from any of the problems we encountered with Multipass. As usual, there's an exception to this general recommendation: if you're a Craft developer who uses a Mac and who has never heard of `sudo` and doesn't use separate admin and user accounts, you might want to give Craft Nitro a shot. If you do so, we'd love to hear about your experience! # Hiccups Source: https://blog.fortrabbit.com/fortrabbit-hiccups-behind-the-scenes Created: 2013-05-21 Author: Frank Lämmer Tags: chronicles > Two weeks of downtimes in 2013, explained from the inside: what broke, what it meant for a young hosting company, and what changed. **Not an easy post to write:** During the last two weeks a few of our customers had to experience some downtimes. Read here what basically is going on and what that means to us. Our "PHP as a Service" just started last October. So far everything had just worked flawlessly and the customer feedback is tremendous. We know that the hosting business is a lot about trust. We have been hosting websites on our old bare metal solution for quite some while, but that is something, not everybody knows. A new service is suspect anyways. When something fails here, it can get quite a drama. > Performance, reliability & security are most important in hosting. Equally most important is developer happiness. We have seen the error occur all of a sudden for the first time about a month ago: One of our nodes had an unusual load-peak. It was killed and restored within a few minutes. This can happen and should not be a big deal. Unfortunately the load problem reappeared on a completely different node some days afterwards. We stopped the line (all development of new features) and concentrated our energy on fixing this. Soon it became clear that it was a networking problem, resulting in a high load on the node. In the start, the event was so seldom, it was hard to catch it and run tests while it occurred. Towards the end of last week, with no good reason, the frequency of the events increased (~two nodes a day). Now the interval seems to move back again to as it was before. Since we started investigating we have ran**thousands of tests** to nail the source of the issue down. So far, we can exclude a lot of possible reason but have not finally found the actual source of the problem - but we're zooming in. I am very happy with the sympathetic feedback of our customers - didn't expected that. **Thank you so much for your understanding.** I really really hope that i don't have to write another post of something that failed very soon. We do the best we can here. I guess most of you guys haven't noticed the issue, since it happened only to a few nodes so far and it usually took only 10 minutes until the system automatically recovered. Apps running on a high availability plan have also not been affected. For us this issue is really a pain, but we're confident to finally resolve it this week or the next. We will keep you updated. * * * **UPDATE 1** 2013-05-22: If you are have deep SysOp knowledge or you are just curious: **[TCP Dup ACK**](https://www.google.com/search?q=TCP+Dup+ACK) might be the trigger of the issue. * * * **UPDATE 2** 2013-05-24: We finally got to the root of the issue and were able to resolve the main problem. We're still monitoring our systems carefully for recurrences but are confident it's gone for good. # fortrabbit is GDPR ready Source: https://blog.fortrabbit.com/fortrabbit-is-gdpr-ready Created: 2018-04-16 Author: Frank Lämmer Tags: chronicles > GDPR is here. Wat is changing for our clients, what not, why and when. TLDR; No action required for for our clients, we are all good. You have some online business? Keep reading, as these changes might affect you as well. DISCLAIMER: This is not a legal advice. This is just our "worst practice". ## Does GDPR apply to me? Yes, you have to keep GDPR in mind, when your online business is based in Europe, or you do business with Europeans. GDPR spans B2B and B2C relations. ## Why is GDPR so good? It is strengthening the security and protection of personal data. That in general is a very good thing. ## Why is GDPR so bad? Just like with other EU laws — hello MOSS — the motives are noble, but the actual technical implementation is to many degrees unclear. For small and specialized businesses — like ours — some rules might be hard to come by with and even be contra-productive. ## Opt-in instead of opt-out Now, for the sake of simplicity, a general rule of thumbs is that everything needs to have an explicit opt-in, instead of a general opt-out. ### Sign-up double opt-in With e-mail double opt-in, a new user first needs to verify their e-mail address before completing the sign-up process. This is a very common practice. So, when signing up to a new service, you first need to check your mail, and click the link to continue. We have a "quick boarding" feature, where users can try out our service right away. The double-opt-in (confirm your e-mail) gets send, while signing up, but, even without clicking the link, the user already has access to the Dashboard to play around and test it. To fully activate the Account, the link in the welcome mail still needs to be clicked. This is not changing, as we believe that we still comply this way and that the delayed double opt-in is a usability win, while still respecting security and privacy. ### E-mail communication opt-in New sign-ups here are also getting subscribed to e-mail communications: #### Transactional mails These are all mails send by the system, some by user interaction, some by time intervals. Common examples are: The before mentioned e-mail opt-in, a forgotten password link, the monthly invoice, the notification that a new collaborator has joined a Company, a reminder that a trial is about expire. Some of those mails are required by law or to make the service fully functional. Others might be marked as "retention" or even "marketing". For the "Trial App ends soon reminder" e-mail, some clients asked us to opt-out or even better opt-in on this. We have considered that carefully and deactivated all transactional e-mails with purpose to keep users engaged. We have compared our service with other similar ones and came to the conclusion, that we are sending very little mail to keep users engaged. On the other hand we get regular "Nobody told me." complains on deleted trial Apps. Yes, we did, with these transactional mails. So this is not going to change now. We are looking into ways to further differentiate here in the future. #### Newsletter Well, how do you define newsletter? Yes, newsletters can get spammy. Our "newsletters" are coming on a very sporadic level (6 newsletters in 2017 ) and they contain quality content that is even sometimes crucial for client communication. Our newsletter informs our clients about important service changes — think: new service features, changes to the TOC and PHP and stack deadlines. There are already options within the Dashboard Account Notifications settings to easily opt-out, as well as a one-click opt-out link in the newsletter. How we have changed this: When signing up, there is a box, that the user agrees to be contact by e-mail by us. This includes transactional mails, possibly downtime communication and newsletters. This checkbox will be required to sign up. ### Terms and privacy opt-in With GDRP, it is now required to actively opt-in to the terms and privacy when signing up. So something like: "By clicking the button above you'll agree to our TOC" is no longer allowed. When signing up, there now is a checkbox, that needs to be clicked. --- #### Signup form before GDPR ![](/images/before-gdpr.gif) #### Signup form after GDPR ![](/images/after-gdpr.gif) --- ## Export and see my data With GDPR, there should be a possibility for the user to download all data. Ideally, that should be available in the Dashboard. Well, I think that makes sense for social networks or any service, where content is generated. Personally, I will be happy to be able to download my posts from Medium. But I hardly can imagine any case this would make sense in a web hosting control panel. Also let's talk about the implementation here, the format for such a download is not defined, so what should a user do with some custom `.xml`, `.yml` or `.json` or `.sql` file? So, this is not going to change here now. It is not required that there is a button for this, so we reserve the right to make this available on support request. ## Forget me The right to be forgotten is also quite a good idea. So, with GDPR in place, the Account deletion, either by client or by us, should actually be: Delete all data; Remove all the clients data from third party services; Remove all backups. Let's have a look: ### Delete all data Well, kind of. It depends. When there is a single Account / Company with some Apps, this mostly applies. All data is getting erased. Expect: for what we need to need to keep for book keeping — 10 years required by law. From a technical point of view, mind that we are in fact deleting all the files of your Apps, all your databases and all database entries with us, but we are not overwriting them with gibberish text seven times. That means that forensic procedures might bring back some of the data. When collaborating with others here: The Account gets deleted, but Company, Billing Contact and Apps might stay there, as there might be other Owners around. We are printing a big yellow warning page on this already. Also, we might have contact via personal e-mail with your clients. We are required by law to keep all business communication for 10 years. We can not delete the e-mails you have sent us and also not the mails we have sent you. We are using Google gSuite for e-mail hosting, so when you write us an e-mail, that is and will be stored there. Nothing changes, I think we are good here. ### Remove data from all third party services So when a client deletes their Account, all external services should be notified to also delete anything related. Let's have a look at what we have in place here: - Intercom support channel — YES, Associated IDs will be deleted when deleting the Account - Credit Card processing — NO, we have to keep billing related data required by law for ten years. The actual credit card details are not stored with us anyways. - Google Analytics and other tracking — YES, as we don't associate our Accounts with user journeys. - Mailchimp newsletter — YES, when you delete your Account, you will be unsubscribed from all newsletters - Statuspage updates — YES, if any. - Additional copies of user data in staging environments — Does not apply. - Postmark App — YES ### Remove Backups When Apps get deleted while deleting Accounts, possible available Backups (when booked with a App plan) will stay around until the retention period is over. So those backups are not getting deleted immediately. We believe that immediate deletion is not in the interest of our clients. We have support cases, where clients accidentally deleted their Apps or even Accounts and are quite happy about provided backups. Also, from a technical point of view, most of those delete actions will be carried out by some kind queue/worker task, so this can't be done on the fly. Nothing is going to change here. Possible available backups will get fully deleted when the retention period ends. ## Restrict processing When an Account is visible to other Accounts, itself should have an option to hide its identity. That totally makes sense for social networks and alike, but in a B2B hosting solution with collaboration features, transparency means security. People making use of our team work features need to know about each other. Would you give code access to a mysterious: "This user prefers to make a secret about himself"? This is not going to change. Other members in your fortrabbit collaboration team will be able to see your: name, e-mail address, avatar and Dashboard history. ## Check 3rd party services to be compliant Yes, as far as we know, for our business everyone is. ## Updated privacy pages Yes, we did a while ago and we have noticed you before. There is a [third party transparency report](https://www.fortrabbit.com/privacy#third-party-services). ## Further readings Oh boy. GDPR is a huge topic in the SEO scene, you'll find thousands of shady copy/pasted articles. But this is a good one: - [GDPR - the practical guide](https://techblog.bozho.net/gdpr-practical-guide-developers/) # Fortrabbit PHPipeline 2013 Source: https://blog.fortrabbit.com/fortrabbit-phpipeline-2013 Created: 2013-01-08 Author: Oliver Stark Tags: chronicles > The fortrabbit roadmap for 2013, written by the person who joined to sit between the technical and the product side of the company. In spring 2012 i joined the Fortrabbit team - namely [Frank](http://franklaemmer.de/) and [Uli](http://foaa.de). Both guys are highly skilled in their fields and very passionate about moving their hosting company to the next level. I became a kind of man-in-the-middle to connect the tech and the marketing/product world - as a person and as a coder (i write the glue code between the frontend and our infrastructure API). It was a great experience to build a hosting platform from the scratch, a product that is still beyond a [MVP](http://theleanstartup.com/principles#develop_mvp) or buggy prototype. ### Current Traction During BETA and the first weeks after launch PHP developers from all over the world were paying attention. [Early](https://twitter.com/thinkdj) [adoptors](https://twitter.com/digitalkookie), some of the [Top](https://twitter.com/seldaek) [of](https://twitter.com/silentworks) [the](https://twitter.com/beberlei) [PHP](https://twitter.com/taylorotwell) [Pops](https://twitter.com/fabpot), web agencies and even competitors tweeted, signed up, played around and gave valuable feedback. **But what's most exciting:** People love the product we've build, they pay money for the service and use it in production. We know that PaaS is still under the radar of many PHP developers. But in 2013 developers, organizations and enterprises will start to rethink their current hosting situation and take advantage of managed cloud environments. ### The Road Ahead The awesome feedback of our customers is the best inspiration for us to build and develop a service that solves real world problems. They ask the right questions and give us hints to make the platform better. So, please [don't stop to ask](http://support.fortrabbit.com/customer/portal/emails/new?emai\[body\]=Hello+fortrabbit) and tell us your ideas. Here is a short list of out upcoming features: * [Optional PHP Extensions](http://fortrabbit.com/feature/optional-php-extensions) * [PHP Runtime in SSH](http://fortrabbit.com/feature/php-runtime-in-ssh) * [Enterprise Products](http://fortrabbit.com/feature/enterprise-products) * [and more](http://fortrabbit.com/roadmap/) if you like ### Company Building Our line-up of three self-motivated guys worked very well to ramp up a very solid core product and we know now it takes time to form a company. Building a team that allows us to make bigger steps and to keep the support on a high level, without losing the fun will be the biggest challenge. It's a shift from a hacker to an entrepreneur. Bootstrapping the first development cycle was a great way to start, but we know that good staff expects a solid salary, so we have to bridge the gap until being profitable. Company funding is a kind of unknown territory for us (we are engineers/designers). Fortunately there are different options we can explore and there are some advisors around guiding us. As you can see, there are many things that will keep us busy in 2013. Let's go for it! # Bephpug Source: https://blog.fortrabbit.com/fortrabbit-talk-bephpug Created: 2012-11-12 Author: Frank Lämmer Tags: chronicles > Slides and notes from the fortrabbit talk at the Berlin PHP user group, given by the person with the least PHP knowledge in the room. We have presented the fortrabbit platform at the last [Berlin PHP usergroup meeting](http://www.bephpug.de/). See the slides [here](https://github.com/berlinphp/berlinphp.github.com/blob/master/folien/fortrabbit-bephpug-2012-11-s.pdf). I am a terrible speaker. Plus that i was totally nervous - knowing to be the guy with the least PHP knowledge in the room, holding a kind of startup pitch talk instead of an interesting tech demo for this really up-to-date audience. So thanks again not only for having us but also for backing us up so much. We really appreciate this and hope that we can contribute more in the future. # User survey results Source: https://blog.fortrabbit.com/fortrabbit-user-survey-results Created: 2013-08-26 Author: Frank Lämmer Tags: chronicles > Results and learnings from our latest questionnaire among our users with 327 answers. We recently did a poll amongst users of our PHP cloud hosting platform. Here are the results and our learnings. As time flies by: Our PHP cloud platform is already available for ten months. We are very happy with feedback and traction so far. By now over 3.500 smart PHP developers are using our service. Seems that we are doing something right. This motivates us for our [ambitious roadmap](http://fortrabbit.com/roadmap). ## Build, measure, learn Apart from product development we are also constantly working on our product-market fit and business strategy. - Are we actually really solving a real problem here? - What are the most important next steps? - Are we attracting our target audience? - Is the pricing right? - Shall we [skip the freemium](http://www.softwarebyrob.com/2010/08/18/why-free-plans-dont-work/) plan or extend it? - Shall we [launch in the US](http://fortrabbit.com/feature/fortrabbit-goes-us) as soon as possible? - How can [support scale](http://fortrabbit.com/feature/support-as-a-service) with increasing demand? To get qualitative feedback we are currently doing a series of direct interviews. Please ping us if you are interested. For a broader more quantitative feedback we recently did a survey amongst our users. So without further bla bla, here is the outcome: ![fortrabbit-survey-results](/images/fortrabbit-survey-results.png) ## Conclusions **Discounts work really well**! We promised all participants of the survey a [voucher code](http://fortrabbit.com/docs/how-to/misc/voucher-code). We got 327 answers, nearly all attendees left their mail address to receive the voucher code. About 3000% more participants than our last survey (with fewer users of course). Like expected we are currently attracting **early adopters** who have already tried out other similar solutions. A lot of people are using the service as an development environment. Most of them work as **freelancers**. That makes sense, because they can decide everything on their own. A lot of users also work as **startups** which surprised us a bit. It's quite hard to find a startup in our neighbourhood on PHP. In Berlin everybody is so hip and writes in Ruby. Our pricing is definitely a topic. When people complain, it's mostly about pricing, while the majority actually thinks it's quite ok. That's a challenge for us. We need to change the way people [think about hosting](/free-web-hosting). It's more a value-based pricing, not so much a consumption-based pricing. So: Thanks again for participating to everyone. # Frank at SaaS Unbound Podcast Source: https://blog.fortrabbit.com/frank-at-saas-unbound Created: 2026-01-13 07:45:09 Author: Frank Lämmer Tags: chronicles > fortrabbit co-founder Frank spends an hour on the SaaS Unbound podcast with Anna Nadeina, talking about bootstrapping hustles. :ContentVideo{videoId='447-9qtdZS8'} saas.unbound is a podcast for and about founders who are working on scaling inspiring products that people love. Brought to you by , a serial acquirer of B2B SaaS companies. They have a few developer facing services as well. # Free web hosting Source: https://blog.fortrabbit.com/free-web-hosting Created: 2013-04-09 Author: Frank Lämmer Tags: opinion > Free PHP hosting is one of the most frequent searches leading to fortrabbit. Why the offer does not exist, and what it would really cost. ## FREE webhosting as long as supplies lasts There is no such thing as free web hosting. That is just a bold headline to catch your attention. ### People are looking for free hosting Looking at search queries leading to our [website](http://www.fortrabbit.com) i find "free php hosting" to be the top five most frequently referrer. Also, Google AdWords constantly suggests to bid on keywords like "free hosting". And, we see that people are especially attracted by the free fact. But hey, we don't do shady business here! Our platform is a really sophisticated high quality hosting service. ![free-hosting-badge](/images/free-hosting-badge.png) ### Free web hosting origins Time warp to the 90s. Until then only big companies could afford to present themselves in the internet. Some universities offered webspace for their students. And the first Hosting services for end consumers came up: Services like GeoCities, TriPod and AngelFire offered free hosting while displaying ad banners. My theory is that this somehow became Facebook and Tumblr later on, but that's a different story. A bit later classical hosting was established. It offered inexpensive shared hosting plans. **Fake-free**: Providers often used "zero price" tags to convey customers that their plans are for free. ### Freemium ![freemium-is](/images/freemium-is.png) Nowadays users are aware of subscription traps. Crippleware to the rescue. Freemium is a low-touch marketing trick: A service provider gives away a core part of the product for free while trying to push the user into a paid plan. For **Software as a Service** the freemium level is mostly fictional: the operating costs are nearly zero. The service is worth … well … what it is worth to you. It save you time, it saves you money, it let's you be more productive, you can do things in a different way, or you can even do things that you haven't been able to do before. Great. Awesome. Basically SaaS providers just have to make sure that the conversation rate from freemium to premium is high enough. For our **Platform as a Service** the same benefit values apply. But we also rent out computing resources and those always cost some real money. That's why it is so hard to offer a real good freemium product here. We want to be as open as possible, let people experience the benefits of our service, but the paid plans should not pay (too much) for these free tiers. We calculated very carefully how much we can spend on this. The result is that Apps running on a free plan are freezing after 48 hours of inactivity. Now, we see that people are annoyed by that: And we can understand it. Our aim is to provide a painless PHP cloud development environment for free. In an ideal world we would like our clients to convert to a paid plan just because they love the service sooooooo much, just like we all purchased a Sublime Text licence, because it is such a nice editor. We see our PaaS colleagues struggle with this as well. Appfog recently [limited](http://blog.appfog.com/new-lower-cost-pricing-plan/) their free ([forever](http://blog.phpfog.com/2011/12/06/php-fog-is-free-forever-and-now-even-more-free/)) offering. DotCloud has even [canceled](http://blog.dotcloud.com/new-sandbox) their freemium plan completely. Quality PHP hosting can't be free. We are evaluating very carefully if and how we can make our free entry level better. # Freemium or free trial? Source: https://blog.fortrabbit.com/freemium-or-free-trial Created: 2013-09-04 Author: Frank Lämmer Tags: chronicles > Is freemium the right business model for our service or shall we switch to a free trial model? My big vision for our service is that your PHP cloud development environment here should be just free of charge. Fall in love with the easy deployment and all the nice features. Then, when comfortable, stay with your project for the hosting when it goes live. Does it work out like this? First of all, it's an easy to communicate message and that's important. Develop for free, pay when you launch. Just as easy to understand as GitHub's free public repos and paid private repos. And to be honest, maybe even more than making shitloads of money, i would also like to create a substantial service enabling people to do cool stuff. GitHub brought open source to new levels. ## In theory At first this model looks very appealing. While in development you don't really need that much resources, so we somehow should be able to give that for free. There is all this talk about resources just getting cheaper and cheaper, soon we will celebrate 50 years of [moores law](http://en.wikipedia.org/wiki/Moore's_law). ## Reality check Turns out that it still costs us about 8 € (only hosting everything else is excluded) to run a development plan for one month. I can hear you think: we are doing something wrong here and it can't be that expensive. Well, maybe. We asked ourselves: **What to expect from a freemium plan?** Something cool and convincing. **Shouldn't the freemium plan also be really reliable?** It should. **Shouldn't the freemium plan include the main features?** It should. **Does it makes sense to develop a complete different free product?** No. ### Disposable hosting The solution is our current freemium plan with the often criticized "freeze" after 48 hours. When an App freezes, we basically turn everything off and put all the contents in a zip file. You can avoid the freeze by logging in to the dashboard and hitting a reset button. This helps us to dramatically reduce our costs. Most apps are idle anyways. You can also unfreeze your Apps and continue working on them, unfreezing might take a couple of minutes. As expected the majority of the free Apps are just frozen. We have around 3.500 Apps, only about 10% are actually "hot". #### Upsides The freemium plan is actually a full featured high quality product with the same great deployment as our paid plans. This model should also work for us as our risks are not that high. The freeze is a good reason for the useres to upgrade. #### Downsides What happened to my original free development vision? Logging in to some dashboard and clicking a button every other day is NOT really comfortable. It's a distraction, it's bad karma. I don't want to force people to update, i want to convince people of the benefits of the paid version. ### Exploring alternatives **Goal**: Realize a better user experience by making continuous development more convenient within the free plan. So we discussed to check for Git receives or SSH/SFTP logins, also total size in bytes might be an indicator. Problem is so far, that no solution here is really perfect. ### Wait a second **Assumption**: If only people are using the service heavily, they will later on convert to a paid plan. Well, well, well. We see that there are some folks out there just using our freemium plan without ever considering to switch. Just recently we got mentioned on a [chinese website for free hosting](http://www.571free.com/mfjz/gw/2013-08/7846.html), now hundreds chinese users come floating in looking for free WordPress hosting. Will they ever convert? Maybe not. We also see that some people figured out how to automate the process of clicking on the reset button. There are some free Apps running for months like this. The funny thing is, the owners seem to have forgotten about their Apps, the bot keeps them alive, but their are no requests on it. That's just a waste. #### Is freemium helping us in other ways? Ok, our main goal is to convert free users to paid users. Maybe there is more: **Understanding the needs of our target audience even better?** Maybe, maybe not, cause the free users are not exactly like out target audience. **Hardening the system, finding deeply hidden bugs?** A little bit, but freemium users don't tend to create edge cases. **Help us solve common misunderstandings?** A little bit maybe. **Bring in other users mouth to mouth that will hopefully convert to paid users?** Maybe some other free users. **Help us make the thing go viral?** We see that paid users have more followers on twitter and like to tweet more about us. **What else have we got then?** The free users make some noise. They ask us questions and keep us busy with this. That sounds a bit negative, but it's not. Free users populating our system gives us live user feedback and let us run into issues early on, which we might see otherwise only months later. ### What's next We are getting more popular, more and more people are signing up to our service and of source are first using the free plan. But we have a limit for the ratio between free and paid apps. And we will soon hit that limit, so it will not be possible any more to create new free Apps, or to unfreeze frozen Apps. The interface will handle this nicely and you can get notified as soon as enough Apps are frozen so that you can start with yours. We must stop the "abuse" of our platform by people looking for the wrong thing. We are not a free hosting service like [000webhost](http://www.000webhost.com/). We would like to support real active development on our platform, we like to see great stuff happening here and it must be hassle free. But as we recently saw, currently a lot of people see us as development platform, not so much for live production. [CodeEnvy](https://codenvy.com/) is just that, a cloud development environment. So, are we giving away too much? --- Bottom line is that we will optimize our boarding process and we have already started a little "communication experiment" for website visitors. ### Further Reading Rob Walling already stated in 2010 that [freemium doesn't work](http://www.softwarebyrob.com/2010/08/18/why-free-plans-dont-work/). This is not the first time i ramble on Freemium, also read my previous posts: [Freemium VS bootstrapped](/freemium-vs-bootstrapped) and [the freemium hosting business model](http://blog.fortrabbit.com/the-freemium-hosting-business-models-our-thoughts/). Or read about [the psychological difference between freemium & free trial plans](http://www.layeredthoughts.com/startups/the-psychological-difference-between-freemium-free-trial-plans), or [why Workable dropped their freemium plan](https://medium.com/p/bfab146c47c8). According to Google [there is even more](http://bit.ly/1a09mQE). # Freemium VS Bootstrapped Source: https://blog.fortrabbit.com/freemium-vs-bootstrapped Created: 2012-09-25 Author: Frank Lämmer Tags: opinion > Building a PaaS in Berlin without venture capital: what bootstrapping decides about pricing, pace and the product itself. Bootstrapped in Berlin - Our startup business model as a PaaS without VC (and the hype). Just like Baron Münchhausen we have to pull ourselves up by our bootstraps. In other words: we have no funding and no big money in the background - and that's alright. Our aim is to build this really great hosting platform for sophisticated PHP developers. We don't want to make a hell lot of money or to find a quick exit, we simply want this kind of development- and hosting-environment for ourselves and hope that like-minded people will also enjoy it. Of course we have a free plan (called BOOTSTRAP). It's mandatory, everybody has one. With a free plan customers can try out the product quickly and without obligations. But we want more than just a trial. Our vision is that the developing area for your apps and websites should always be free. The free plan should really be something you can work with. Unlike a SaaS startup our platform as a service is about real hardware resources and we actually have to pay for your free plans. > Are the razors any good? No. They are f****** great. There is no such thing as free hosting, someone always got to pay. Our free version is not slimmed down. It already has all of the nice features (such as writable storage, git-push deployment, composer integration…). The question for us was: How can we be open for us much users as possible without wasting resources? Our answer is the _freeze mode_. An unused (currently after 48 hours of inactivity) free plan will automatically be shut down and archived. We think that this totally OK for an app in development. You might have just used the free plan to check out the service. If you need it again, you can wake it up with a click in the control panel. Unfreezing an app takes about 5 minutes. We have calculated very carefully and we hope that we can loosen the limitations in the future bit by bit. ### Further readings * [Our previous thoughts on freemium hosting](/the-freemium-hosting-business-models-our-thoughts) * * * ### UPDATE (2012-10-11) We are listening and already elaborating ways to make the situation better. The goal is of course that you should be able to develop your App here for free without any hassle or interruptions. But we also need to shut down all "does_it_really_work_that_way" Apps as soon as possible. We might extend the "real freeze" time a bit. In fact there is a soft freeze (just chill) where unfreezing just takes a minute and a hard freeze. We might reset the timer with each Git-Push-Deploy or we even compare the footprint of the App. # Working with geographic features and spatial data in MySQL 8 Source: https://blog.fortrabbit.com/geographic-features-spatial-data-mysql-8 Created: 2021-03-01 Author: Jascha Silbermann Tags: webdev > Use MySQL 8 as a spatial database: geometry types, spatial indexes and distance queries, with PHP examples that run on fortrabbit. With the release of MySQL 8 in the spring of 2018, a mature set of features has entered the mainstream. Having previously taken a closer look at the [JSON data type](/mysql-json-column-with-laravel), we now turn our attention to spatial data. Specifically, we will discuss how to **employ MySQL 8 as a spatial database** to store and process geographic features. Before we get to the nitty-gritty details, such as how to write spatial queries, let's consider a few basic questions: **What is spatial data, and what are geographic features?** ## Storing geographic features using spatial data Spatial data, as explained by the [MySQL reference](https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html) is geometric data defined as **"a point or an aggregate of points" representing anything in the world that has a location**. The Open Geospatial Consortium (OGC) publishes a set of standards under the label Geospatial Information and Standards (OpenGIS). The OpenGIS geometry model defines different types of geometry for representing spatial data. The different **geometry types serve as an abstract basis to model spatial data**. Within a spatial database, we furthermore encounter a number of key technical concepts: * Geometric functions for manipulating spatial data and converting between textual and internal representations. * Geometric functions for computing spatial relations between different geographic features. * Spatial indexing for improved access times to spatial columns. All of these serve to **model, process, and compare the geometry** of geographic features. ### Geographic features, a definition Geographic features describe **entities that have a physical location in the real world**. According to the [MySQL reference](https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html), a geographic feature can be: > * An entity. For example, a mountain, a pond, a city. > * A space. For example, town district, the tropics. > * A definable location. For example, a crossroad, as a particular place where two streets intersect. A geographic feature exists in the real world. To describe it in terms of spatial data, we make use of geometric objects. The OpenGIS geometry model defines two basic hierarchies of geometric objects. ### Simple geometric objects Each simple geometric object defines a **single geographic feature**: * `Point` * `LineString` * `Polygon` There is also the purely abstract `Geometry` type of geometric object, which can represent any of the other geometry types. ### Compound geometric objects Each compound geometric object defines a **collection of features**. The following compound geometric objects are available as per the spec: * `MultiPoint` * `MultiLineString` * `MultiPolygon` Analogous to the abstract `Geometry` geometry type there is a corresponding `GeometryCollection` compound geometric object. This can represent any of the other compound geometric objects. ### Coordinate reference systems A geometric object consists of points in space. To anchor a geographic feature within the real world, the corresponding geometric object needs to be linked to a known coordinate reference system. Such a system is also **commonly called a "spatial reference system"**. Only when the coordinate reference systems for two geometric objects are known can we reason about the spatial relations between the two objects. | SRID | Description | Unit | |:--|:--|:--| | `4326` | GPS satellite navigation system; also used for NATO military geodetic surveying. | degrees | | `3857` | Web mapping and visualization applications: Google Maps, Open Street Maps, etc. | meters | ## Spatial databases for geographic features: MySQL 8 vs 5.7 compared Better support for spatial data handling was one of the major improvements included in the MySQL 8 release. However, it **was already possible to store and process geographic features using earlier MySQL versions** as well as competing database systems. We won't go down the =MySQL vs PostgreSQL=, or MySQL vs MariaDB rabbit hole. Instead, we focus our attention on the direct comparison of using MySQL 8 vs 5.7 as a spatial database. ### How has spatial data handling improved in MySQL 8 The first major improvement brought forth by MySQL 8 was better support for coordinate reference systems a.k.a. spatial reference systems (SRS). Remember that to **anchor a geographic feature in the real world** requires for the the corresponding geometric object to be assigned a spatial reference system. With MySQL 8, a number of different spatial reference systems have become available. To **compute spatial relations between two different geometric objects**, both objects need to be placed within the same spatial reference system. Below we give an overview of the three kinds of spatial reference system available in MySQL 8: | Type of spatial reference system (SRS) | Explanation | Coordinates | Units | |:--|:--|:--|:--| | Projected SRS | Projection of a globe onto a flat surface — a map | Cartesian | Distance units: meters, feet, etc. | | Geographic SRS | Non-projected — an ellipsoid | Latitude-longitude | Any angular unit | | SRS with SRID `0` | Default SRID for spatial data in MySQL | Infinite flat Cartesian plane | Unitless | While spatial reference systems are not a new concept in MySQL, with version 8.0 they directly affect computation. Each spatial reference system is **denoted by a spatial reference system identifier (SRID)**. There are more than 5,000 spatial reference systems to choose from. To give a few tangible examples, the [MySQL Server Team](https://mysqlserverteam.com/spatial-reference-systems-in-mysql-8-0/) notes: > SRID 4326 is GPS coordinates. SRID 3857 is the web map projection that you see on Google Maps, OpenStreetMap, and most other web maps. The second major improvement to spatial data handling in MySQL 8 pertains to **spatial indexing, that is, the optimization of columns holding spatial data**. Two requirements have to be met for spatial indexing to work properly: 1. The geometry columns to be included in the index need to be defined as `NOT NULL`. 2. Columns need to be restricted to a spatial reference system identifier (SRID), and all column values must have the same SRID. ### How was spatial data handled in MySQL 5.7? While it has been possible to store a spatial reference system identifier (SRID) with a geometric object, MySQL versions prior to 8.0 were not able to use this information for computations. Instead, the provided **geometric functions operated on the infinite flat Cartesian plane** represented by SRID `0`. To get accurate results, one commonly had to define custom functions to process raw results and convert between units. Writing custom functions for querying and processing of geographic features **required an intimate understanding of math and geometry**. Furthermore, many of the provided spatial relations functions were limited to using the minimum bounding rectangle (MBR), instead of the precise shape of geometric objects. ## Spatial queries in MySQL 8 So far, we've looked at what constitutes a geographic feature, as well as how geographic features are represented as spatial data. We now turn our attention to the **specific technical implementation** found in MySQL 8: * How to create, populate and index database tables holding spatial data. * How to compute spatial relations between geometric objects, and how to retrieve specific pieces of spatial data. Specifically, since we're using **SQL ("structured query language") as the interface between the database and the user**, we'll be discussing the spatial queries involved. But first, a bit of background. The Open Geospatial Consortium (OGC) publishes a set of standards under the name "OpenGIS Simple Feature Access". These are also normed as `ISO 19125-1`, and `ISO 19125-2`. The `ISO 19125-1` **standard defines two representations for the exchange of geometric objects** across systems. In particular, the standard defines the **"Well-known Text" (WKT) representation of geometry**, which provides a human-readable, text-based representation for the definition of geometric objects. Furthermore, "Well-Known Binary" (WKB) is a corresponding, machine-readable binary representation. Specific technical implementations providing Simple Feature Access exist for different database management systems: | Database management system | Simple Feature Access extension | |:--|:--| | MySQL | MySQL Spatial Extensions | | PostgreSQL | PostGIS Extension | | SQLite | SpatiaLite Extension | ### What does a spatial query look like? For the most part, spatial queries are **just ordinary SQL queries**. There are, however, some particularities that make spatial queries stand out: * Spatial queries employ the different geometry types defined in `ISO 19125-1` as data types for the creation and population of database tables. * Spatial queries commonly feature Well-known Text (WKT) representations of spatial data; this is particularly the case for queries that add geographic features to the database. * Spatial queries make use of `ST_`-prefixed functions for computations and transformation of spatial data. Note: in the examples below we are often using the SQL `SET` statement to define variables. This is not necessary per se, but makes for cleaner code and more easily understood queries. #### Creating a table to hold spatial data Create a new table `spat` with a column `geom` of type `Geometry`: ```sql CREATE TABLE spat (geom GEOMETRY); ``` Remember that this allows us to store geometric objects of any geometry type. We can also be more specific; here we add a new column of type `Point` to the existing `spat` table: ```sql ALTER TABLE spat ADD pt POINT; ``` #### Inserting spatial data into the database We've mentioned the Well-known Text (WKT) format a few times, but what does it actually look like? Here we **use WKT to define a point and process the textual representation** by calling the `ST_GeomFromText()` function: ```sql SET @g1 = 'POINT(1 1)'; INSERT INTO spat VALUES (ST_GeomFromText(@g1)); ``` Specialized functions exist for the different types of geometry. As an example, here we employ the `ST_PointFromText()` function to process a WKT-string representing another point: ```sql SET @g2 = 'POINT(2 3)'; INSERT INTO spat VALUES (ST_PointFromText(@g2)); ``` Calling these functions will transform the WKT-representation into an internal storage format. #### Retrieving spatial data from the database Once we have spatial data stored inside the database, we'll commonly want to extract the data. Again, we use **Well-known Text (WKT) as the universal interface**. Here we're calling the `ST_AsText()` function to retrieve the column `g` from and convert its contents from the internal representation back to WKT: ```sql SELECT ST_AsText(geom) FROM spat; ``` Correspondingly, we can use the `ST_AsBinary()` function to convert the contents of the `geom` column to a compact binary representation: ```sql SELECT ST_AsBinary(geom) FROM spat; ``` #### Using geometric functions to compute spatial relations One of the most practical uses of a spatial database is to query the spatial data according to certain spatial relations. This allows us to **ask questions about the geometric objects**, such as "find all objects that are located within / outside of a particular object". Some of the more commonly used spatial relations are: | Spatial relation | Corresponding `ST_`-function | Set-theory explanation | |:--|:--|:--| | Equals | `ST_Equals()` | (a ∩ b = a) ∧ (a ∩ b = b) | | Disjoint | `ST_Disjoint()` | a ∩ b = ∅ | | Intersects | `ST_Intersects()` | a ∩ b ≠ ∅ | | Touches | `ST_Touches()` | (a ∩ b ≠ ∅) ∧ (aο ∩ bο = ∅) | | Contains | `ST_Contains()` | a ∩ b = b | | Within | `ST_Within()` | a ∩ b = a | All of these spatial relations compare the location of two geometric objects and return a boolean (true / false) result. **Besides these boolean relations, there are a number of functions to calculate the distance between geometric objects**. In these cases, the returned value will be numeric. The unit of the result depends on the spatial reference system (SRS) in use. Here we calculate the distance between two points in the SRS defined by SRID `4326`: ```sql SET @g1 = ST_GeomFromText('POINT(1 1)', 4326); SET @g2 = ST_GeomFromText('POINT(2 2)', 4326); SELECT ST_Distance(@g1, @g2); ``` #### Using spatial indexing to improve performance of spatial queries Indexing of database columns is a best practice to improve query performance. As was the case in MySQL 5.7, creating a **spatial index in MySQL 8 results in an "R-tree" data structure**, which is optimized for quickly resolving many spatial relations. Remember that for spatial indexing to work, the column to be indexed must be declared `NOT NULL`and must have an SRID set: ```sql CREATE TABLE spat (geom GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX(geom)); ``` ### Popular geospatial libraries for working with geographic features and spatial data In real-world applications it may not be practical to write out spatial queries using Well-known Text (WKT) by hand. Fortunately, a number of libraries exist to make this job easier. They allow for the **programmatic mapping between different representations of geographic features**, such as natural language coordinates, Well-known Text/Binary, and GeoJSON. Here's a selection of popular geospatial PHP libraries: | Library / Package | Description | |:--|:--| | [GeoPHP](https://geophp.net/) | PHP library for working with geometric objects and geometric functions. Works with a range of formats, including WKT, WKB, and GeoJSON. Used to get centroids, bounding-boxes, area, etc. of a geometric object. | | [Geocoder](https://geocoder-php.org/) | Get precise geographic coordinates for a geographic feature, such as "Buckingham Palace, London". Supports a wide range of providers. | | [grimzy/laravel-mysql-spatial](https://packagist.org/packages/grimzy/laravel-mysql-spatial) | Facilitate working with spatial data and spatial relations in Laravel. | | [sjaakp/yii2-spatial](https://packagist.org/packages/sjaakp/yii2-spatial) | Provide spatial data support for ActiveRecords in the Yii2 framework. | | [creof/geo-parser](https://packagist.org/packages/creof/geo-parser) | Parse coordinates from their natural-language string representations, such as `'79°56′55″W, 40°26′46″N'`. | | [pragmarx/countries](https://packagist.org/packages/pragmarx/countries) | Retrieve country-specific information. Geographic features include states, cities, and borders. Accepts many different formats as input, such as common names, ISO codes, etc. | ## References ## Sources * [MySQL :: MySQL 8.0 Reference Manual :: 11.4 Spatial Data Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html) * [MySQL :: MySQL 5.7 Reference Manual :: 11.4 Spatial Data Types](https://dev.mysql.com/doc/refman/5.7/en/spatial-types.html) * [Simple Feature Access - Part 2: SQL Option | OGC](https://www.ogc.org/standards/sfs) * [Playing with Geometry/Spatial Data Types in MySQL | by Uday Hiwarale | System Failure | Medium](https://medium.com/sysf/playing-with-geometry-spatial-data-type-in-mysql-645b83880331) * [Geography in MySQL 8.0 | MySQL Server Blog](https://mysqlserverteam.com/geography-in-mysql-8-0/) * [Spatial Reference Systems in MySQL 8.0 | MySQL Server Blog](https://mysqlserverteam.com/spatial-reference-systems-in-mysql-8-0/) * [Simple Features - Wikipedia](https://en.wikipedia.org/wiki/Simple_Features) # Goodbye and hello Source: https://blog.fortrabbit.com/goodbye-hello Created: 2025-11-14 16:10:14 Author: Frank Lämmer Tags: changelog > A farewell to the old fortrabbit design — sharp rectangles, a custom SCSS framework, Raleway — and a first look at what replaces it. ## What goes away Goodbye sharp rectangles. Farewell custom CSS framework built in SCSS. See you Raleway. ![Homepage page](/images/screenshot-01-homepage.png) ![Pricing page](/images/screenshot-02-pricing.png) ![Landing page](/images/screenshot-03-landing-page.png) ![Specs page](/images/screenshot-04-specs.png) ![Help index page](/images/screenshot-05-help.png) ![Blog index page](/images/screenshot-06-blog.png) ## What is coming Hello rounded boxes. Hi Tailwwind. Hi Hubot. :ContentVideo{videoId='W5KHnHuPC2o?si=egoz9Bd6H9Fsu2PU'} [More details](https://docs.fortrabbit.com/platform/new/) # Goodbye WebRechnung Source: https://blog.fortrabbit.com/goodbye-webrechnung Created: 2013-01-10 Author: Frank Lämmer Tags: chronicles > fortrabbit shuts down WebRechnung and the remaining MISH services, to put everything behind the new PHP hosting platform. **Goodbye to you, my trusted friend.** We are busy with our new [PHP developer cloud hosting](http://fortrabbit.com). Currently we are preparing to shut down our old MISH services on the 30st of April 2013 in favor to the new platform. A part of MISH is WebRechnung and we finally decided to take it down without replacement. WebRechnung was a free service to create and send invoices and estimates online - similar to FreshBooks, but especially designed to fit to the German tax laws. We have failed to make it a real business. This article is about our lessons learned. See WebRechnung in action in the video above. ## History #### The Need By the beginning of 2010 we needed to generate invoices for our old hosting solution MISH. We looked around and as we found nothing at first glance that looked cool enough for us we decided to build something on our own right away. > The three chief virtues of a programmer are: Laziness, Impatience and Hubris. Larry Wall It turned out that it became a really useful tool. Our friends and ourselves began using it immediately for any kind of invoicing. So we launched WebRechnung (WebInvoice) as a stand-alone product in September 2010. #### The business strategy It feels a bit strange when i think about it now: WebRechnung could be used stand-alone, but was implemented and tightly intervened with our original MISH hosting solution. The idea was that people who need online invoicing could also use our hosting and vice versa: You only need one login to manage your hosting account and your invoicing - isn't that cool? Well, maybe not. Most of our hosting clients never logged in to WebRechnung or the other way around - no real synergy effects. After we fixed some teething troubles in the first months, WebRechnung soon became a mature product with all essential features. It was just cool like that. We have had some competitors (EasyBill, Salesking, Billomat, FastBill, Collemx, LexLive …) but our product and it's price where really good, I think. However the sales never really took off. So we neglected it a bit. #### Set it free By the end of 2011 we only had about 50 paying customers with an overall monthly revenue of something like 300 €. We decided that we should focus on our core product hosting and put no more energy in this invoicing tool. We didn't wanted to feel too responsible for our few paying customers. So we removed all costs (aside from the one we had ourselves: sending invoices via snail mail). So we had a professional developed billing software for free - no handicapped freemium crap. My secret hope was that maybe now it will have a positive effect on our hosting or the invoice user base could increase to a critical mass so that we could think about a business model again. More contacts should help to manifest the fortrabbit brand, improve our Google ranking and so on. With enough users we might have even been able to bring back some new "premium features". #### Still not enough success It turned out that even this bold move didn't made any real impact. About two years after the launch and one year after removing all costs from it we still only had about 200 users really using it. Sometimes it's not enough to have a good service for an unbeatable price. You must be visible in a competitive market. We didn't had any marketing, nor social media activities, nor public relations, nor customer relation ship management going on. I think that this was our biggest mistake. ### Seeking possibilities to continue Our main problem with WebRechnung is that it doesn't fit our standards any more - software, as everything, degrades over time. The interwebs is moving fastly forward, everything is evolving. Adapt or die. We don't want to see this old piece of software (base core is 3 years old now) out there into the wild much longer. #### What about Open Sourcing it? We would love to publish it on GitHub. Unfortunately this software is not really a modern ninja style stand alone application. It is tightly integrated into our monolithic MISH system - mostly written in Perl and impossible to understand for an outsider anyways. And it's really old: dependencies are outdated, large parts of the code are in need of major re-factoring. We would rather rewrite everything before touching this code again. #### What about crowdfunding it? I thought about a kickstarter campaign for a while. But we are into this new [PHP developer hosting platform](http://fortrabbit.com/) now and that is actually much more interesting for us. We need to focus, we don't have the manpower to develop and maintain such a huge side project. Dear existing clients, i am personally very sorry to bring you such bad news. It was a really hard decision for us, but i hope you can understand us after reading this. The good news is, that there really similar services out there. I have named some on our product site: [webrechnung.info](http://webrechnung.info). The beginning of the year is a good time to change your invoice tool. **We had joy, we had fun, we had seasons in the sun.** Some more comments on [HN](http://news.ycombinator.com/item?id=5037142). # Growing ANAME / ALIAS support Source: https://blog.fortrabbit.com/growing-aname-alias-support Created: 2025-07-08 14:54:40 Author: Frank Lämmer Tags: webdev, dns, domains > Standard DNS forbids CNAME records at the apex. More providers now offer ANAME and ALIAS records that route a bare domain to a host. ## The problem with apex domains You want to route your apex domain (also called bare or naked domain) like `example.com` directly to your app hosted at `myapp.frb.io`. With standard DNS you cannot use CNAME records at apex domain level. - **CNAME records** would solve the routing but break email delivery - **A records** require IP addresses, which don't work with dynamic hosting services - **Email MX records** cannot coexist with CNAME records at the apex Read our [help article on bare domains](https://help.fortrabbit.com/bare-domains) for more technical details and to understand whether you actually need apex domain routing. ## The (non-standard) solution Different providers use different names for essentially the same functionality: - **ANAME** (Address Name) - **ALIAS** - **CNAME flattening** But they all work the same: 1. **Acting like CNAME records** - They resolve to the target hostname 2. **Working at the apex** - Unlike CNAME, they can be used for bare domains 3. **Preserving email** - They don't interfere with MX records ## Supported providers The following DNS providers support apex domain routing through ANAME/ALIAS records: ### Major cloud providers - [**AWS Route53**](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html) - ALIAS records - [**Cloudflare**](https://developers.cloudflare.com/dns/cname-flattening) - CNAME flattening - [**Google Cloud DNS**](https://cloud.google.com/dns/docs/records-overview#alias-records) - ALIAS records ### Specialized DNS providers - [**DNS Made Easy**](https://support.dnsmadeeasy.com/support/solutions/articles/47001001412-aname-records) - ANAME records - [**DNSimple**](https://support.dnsimple.com/articles/alias-record) - ALIAS records - [**EasyDNS**](https://kb.easydns.com/knowledge/aname-records) - ANAME records ### Domain registrars with DNS - [**Dreamhost**](https://help.dreamhost.com/hc/en-us/articles/360035516812-Adding-custom-DNS-records) - Custom DNS records - [**Namecheap**](https://www.namecheap.com/support/knowledgebase/article.aspx/10128/2237/how-to-create-an-alias-record) - ALIAS records - [**Porkbun**](https://kb.porkbun.com/article/68-how-to-edit-dns-records) - ALIAS records ## Setting up ANAME/ALIAS records The exact process varies by provider, but generally involves: 1. **Log into your DNS management panel** 2. **Create a new record** at the apex domain (`@` or blank) 3. **Select ANAME/ALIAS** as the record type 4. **Enter your target hostname** (e.g., `myapp.frb.io`) 5. **Save the record** and wait for DNS propagation ## Providers without support Some major providers still don't support ANAME/ALIAS records: - **GoDaddy** - No ANAME support ([Stack Overflow discussion](https://webmasters.stackexchange.com/questions/141075/aname-record-not-accepted)) - **1&1 IONOS** - Limited DNS record support - **Network Solutions** - Traditional DNS only ## What to do if your provider doesn't support it If your current DNS provider doesn't support ANAME/ALIAS records, you have several options: 1. **Switch DNS providers** - Move to one of the supported providers above 2. **Add a third-party DNS** - Keep your domain registered where it is, but use a different provider for DNS 3. **Use www forwarding** - Redirect `example.com` to `www.example.com` ## Our conclusion Since most browsers omit the www prefix and users barely notice it, we recommend using a simple forwarding service instead of ANAME/ALIAS/CNAME flattening. We don't think the aestehtic reasons hold up, as outlined with [our help article](https://help.fortrabbit.com/bare-domains#toc-our-opinion-about-bare-domains). You don't lock yourself in. There are no SEO implications, even if you move from bare to www domain. Fo our upcoming platform at [new.fortrabbit.com](https://new.fortrabbit.com) we explore CDN integration, that may change DNS routing. # About Composer Source: https://blog.fortrabbit.com/handle-your-dependencies-with-php-composer Created: 2012-09-03 Author: Ulrich Kautz Tags: webdev > An introduction to Composer for PHP developers who have not used a dependency manager yet, and how it fits into deployment. ## Composer - Sounds Good [Composer](http://getcomposer.org/) describes itself as "a tool for dependency management in PHP". It uses a large [repository of packages](http://packagist.org/packages/) which is continuously extended and maintained by the community. It is now out there for about a year or so. This article goes out to everybody who is not already using it: we want you to give it a try it and here is why. ## How it works In short: You can install PHP packages, for example the [Symfony framework](http://symfony.com/) or [Twig](http://twig.sensiolabs.org/), from the command line. The developers of Composer call it a dependency manager, not package manager, because it does not install packages globally (eg like Debian apt, Ruby gem, Perl CPAN) but only on a "per project" basis - read: in a (project) directory. The package code is managed either with Git or Mercurial (or supposedly Subversion), which comes in handy if you want to stay state of the art. Each package can itself declare dependencies to other packages (duhh), so you can "hassle free" choose what you need and composer will do the rest for you - and keeps you up 2 date. ## Why it's a great idea Most popular scripting languages, which are used for web development, have at least one package management of some kind. Ruby has [Bundler](http://gembundler.com/), Python has [pip](http://www.pip-installer.org/), Perl has [CPAN](http://metacpan.org/) and NodeJS has [npm](https://npmjs.org/). If you've never worked with any of those, you probably don't know what you've been missing: Working with plain archive files (as it used to be the case with PHP libraries) is messy, slows you down and increases risks by not having easy update mechanisms which makes you vulnerable for the most annoying kind of security issues - already fixed ones. The benefit of a package (or dependency) manager in general and Composer in particular are: * Decreases development time, as finding and downloading required libraries from a centralized repository is much simpler than researching the web. * Easy access of libraries leads to more people re-using existing code, which will improve and harden it (many eyes..). * The possibility to simply get one's own code out there thrives the community. * Automatic dependency management encourages developers to publish new packages while relying on old ([DRY](http://de.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself)). * Finally: All of the above makes PHP a better choice than before, if you have to justify what language your next project will be written in. ## Quick installation First you need to download the composer phar file. The quick way: ```bash curl -s https://getcomposer.org/installer | php ``` This will download and execute an installer code, which will download an executable `composer.phar` file. Move this file somewhere in your `$PATH`, eg `/usr/local/bin`, so you can execute it like this on the terminal: ``` sudo mv composer.phar /usr/local/bin/composer composer --version ``` If this prints out something like the following, you are good to go (if not, visit [the official installer guide](http://getcomposer.org/doc/00-intro.md#installation) and follow the instructions). ``` Composer version e2f8098 ``` ## Example Let's install Twig, a template engine for PHP (yes, i believe in the separation of code from view ;)). You could now just download and unpack the twig libraries, but let's do it right the first time. Create the dependency file `composer.json` in your project folder, containing: ```json { "require": { "twig/twig": "1.*" } } ``` Now go to your project dir and install twig by running ```bash cd MyProject composer install ``` You should see something like this: ```bash Loading composer repositories with package information Installing dependencies - Installing twig/twig (v1.9.2) Downloading: 100% Writing lock file Generating autoload files ``` Afterwards, you have a directory `vendor` which contains some composer files and the the sub directory `twig/twig`, where twig was installed in. Cause we are on it, let's also install Doctrine. Use `composer` to search for it: ```bash $ composer search doctrine | grep orm ... doctrine/orm: Object-Relational-Mapper for PHP a2lix/translation-form-bundle: Translation field to use with Translatable Doctrine extension ... ``` The search is still a bit messy, so i've narrowed it down with `grep orm`... However, you should see _doctrine/orm_. Now let's look what versions are there: ```bash $ composer show doctrine/orm name : doctrine/orm descrip. : Object-Relational-Mapper for PHP keywords : database, orm versions : dev-master, 2.4.x-dev, 2.3.x-dev, 2.3.0-RC1, 2.3.0-BETA1, 2.2.x-dev, 2.2.3, 2.2.2, 2.2.1, 2.2.0, 2.2.0-RC1, 2.2.0-BETA2, 2.2.0-BETA1, 2.1.x-dev, 2.1.7, 2.1.6, 2.1.5, 2.1.4, 2.1.3, 2.0.x-dev, dev-join-poc, dev-DDC-1766, dev-DDC-1652, dev-DDC-1637, dev-DDC-1544, dev-DDC-1509, dev-DDC-1385, dev-DDC-1383, dev-DDC-720, dev-DDC-551, dev-DDC-217, dev-DCOM-93, dev-DDC-93, dev-Test, dev-ImproveErrorMessages, dev-feature/flush-many-documents type : library ... ``` This will give you a bunch of information, among them which versions are available and what PHP versions is required and so on. Let's use the latest 2.2 version (the others are currently RC or dev as of this date). Extend the `composer.json` like this: ```json { "require": { "twig/twig": "1.*", "doctrine/orm": "2.2.*" } } ``` Now run update (not install). It will download the _doctrine/orm_ as well as _doctrine/dbal_ and _doctrine/common_ onto which it depends. ```bash $ composer update Loading composer repositories with package information Updating dependencies - Installing doctrine/common (2.2.2) Downloading: 100% - Installing doctrine/dbal (2.2.2) Downloading: 100% - Installing doctrine/orm (2.2.3) Downloading: 100% Writing lock file Generating autoload files ``` And that's it. Now you've all you need. You can run `$ composer update` later on to make sure you have the latest. You can now include the files in your own boostrap (eg `index.php`) file: ```php require_once __DIR__ . '/vendor/autoload.php'; ``` Hope you are as delighted as we are about Composer and will use it in your future projects! ### Other Articles on Composer PHP * [Henri Bergius on Composer](http://bergie.iki.fi/blog/composer_solves_the_php_code-sharing_problem/) * [Composer What & Why by Nelm.io](http://nelm.io/blog/2011/12/composer-part-1-what-why/) * [Easy Package Management With Composer](http://net.tutsplus.com/tutorials/php/easy-package-management-with-composer/) by Philip Sturgeon on NetTuts Now head over to the [Composer website](http://getcomposer.org/doc/) and install it. # Headless PHP Source: https://blog.fortrabbit.com/headless-php Created: 2025-11-03 08:16:08 Author: Frank Lämmer Tags: opinion > Decoupled systems with a JavaScript frontend and a PHP backend: what headless actually means, how it is built, and when it pays off. ## What is headless? A software system where the front end (user interface) is separated from the back end (content management). It's called headless, because the backend content system is now missing the part where it renders the frontend. This decoupled dual stack approach consists of two independent systems that talk to each other. - The backend provides an API (REST, GraphQL). - The frontend is based on JavaScript (Svelte, Next.js, Nuxt.js, Astro …) ### PHP as the backend The backend of a JAMstack can be anything. From a Firebase database, to a hosted CMS like Contentful. We provide PHP hosting. So let's look into that. #### CMS systems Traditional PHP CMS systems bundle the backend and the frontend into one system. But a headless mode is now available for WordPress, Craft CMS and many more. - [getkirby.com/…/headless-getting-started](https://getkirby.com/docs/cookbook/headless/headless-getting-started) - [craftcms.com/…/graphql.html](https://craftcms.com/docs/getting-started-tutorial/more/graphql.html) - [statamic.dev/rest-api](https://statamic.dev/rest-api) #### PHP frameworks PHP frameworks like Laravel and Symfony support API interfaces as well. The PHP backend system and the frontend system can live in separate codebases and can be developed and deployed independently. This makes it interesting for bigger teams or projects as well as frontend focused developers. The frontend website is just one client for the backend, another one might be a mobile app. The use of Single Page Applications is a trend. Carefully consider if such a system is the best technology for the given project. For decoupled projects, the individual parts can be deployed to different web hosts: - PHP backend: a service that has a PHP runtime. - JS frontend: a dedicated JAMstack hosting service. This is sophisticated, more complex and more expensive to host. It's also important to choose the correct delivery mode that comes with strings attached in regard of hosting: ### Client Side Rendered (CSR) This is the classical Single Page App (SPA) style. All the data is provided by the API to the frontend via AJAX calls. The website is constructed in the browser when a human visits. #### CSR hosting Best use CSR (classical SPA) for app-like projects, not websites. Something that has a login and does do not require any SEO. The frontend and the backend can be indipendently deployed and hosted. The frontend is cheap to host, since it's just some text files. It can also be put on the edge. ### Server Side Generated (SSG) During build time, usually during deployment, the whole frontend content is pre-rendered as static HTML pages. The initial load will display the static page (fast), then the SPA mode kicks in (client hydration) and serves every click from them then on. #### SSG hosting SSG works great for small sites with mostly static content and not even a requirement of a backend (classic JAMstack). As a developer, you may have a blog where the content consists of a bunch of markdown files, that are part of the repo. So every time you write a new blog post, you just need to deploy to set it online. SSG is cheap to host. A CMS backend is needed when a non-technical editor is supposed to edit contents. But what should happen when an editor changes the content of an article with a SSG system? The new content is available through the REST or GraphQL API once the hydration is finished, but not statically generated yet. It's possible to trigger new deployments after edits, but re-generation of a full website after a minor change is wasteful, fragile and slow. ### Server Side Rendered (SSR) Server Side Rendering is a confusing term because it's not designating classical websites but a strategy to pre-render content on the server before the CSR kicks in (client hydration). Search engine crawlers can parse it. SSR always serves up-to-date content without JavaScript enabled, thus is good for SEO. Yet it still provides that SPA feeling. #### SSR hosting SSR requires a Node.js runtime on the frontend stack server to query the backend to return HTML directly to the browser. That means you need two servers to host one website: - Backend server provides the API - Frontend server queries the API to return HTML The frontend can not be hosted on the edge. It's good for SEO. Always creating pages from the source is slower than directly spitting out static pages. ### Incremental Static Regeneration (ISR) ISR is one approach to solve shortcomings of SSR and SSG. 1. The first unlucky user visits a page that is outdated 2. The old static version is served first 3. The dynamic version kicks, with updated content (hydration) 4. The Node.js has detected old content server creates an updated static version 5. The next lucky visitor will be served the updated static content #### ISR hosting This of course also requires two servers for one website: - Backend server provides the API - Frontend server creates new static pages on the fly The frontend however can still be hosted on the edge. It's good for SEO and it is fast. But it's more complex to setup too. It's also not the cheapest option. ## My takeaway The JAMstack evangelists promise a fast future on the edge. The technology is genuinely impressive, yet complex. More moving parts means higher hosting costs. Think twice, not every project justifies this investment. For small and mid-sized website projects, I still would recommend to explore server-side rendered PHP. It's faster to develop, easier to deploy, and more affordable to host. In my humble opinion, the simplicity often outweighs the architectural superiority that decoupled systems provide. It's also a matter of personal preference, many full stack developers enjoy working with JavaScript these days. # Heartbleed Source: https://blog.fortrabbit.com/heartbleed-openssl-vulnerability Created: 2014-04-08 Author: Ulrich Kautz Tags: changelog > This exploit is a vulnerability in the heartbeat of TLS in the OpenSSL implementation. We're patched up by now. ## Heartbleed - fortrabbit is patched If you read about any news feed today, you probably have read about the [Heartbleed Bug](http://heartbleed.com/) by now. This bug affected most of supposed-to-be-secure parts of the interwebs. ## Summary Heartbleed, aka [CVE-2014-0160](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160), is a vulnerability in the OpenSSL library. This library is utilized by many major open source server applications. Among those most web server implementations, about any IMAP/POP3 or SMTP server and a lot of VPN servers. The vulnerability was published in the night from yesterday. It allows attackers to misuse a TLS extension called [heartbeat](http://tools.ietf.org/html/draft-ietf-tls-dtls-heartbeat). Heartbeat is basically a keep-alive mechanism, which reduces the overhead of continuous TLS re-negotiation. The exploit: Attacker sends a bad heartbeat package. Server responds with 64KB of memory which it's not supposed to send. Now what those 64KB _can_ contain is the problem. More on that later. A really good and detailed explanation can be found [here](http://blog.existentialize.com/diagnosis-of-the-openssl-heartbleed-bug.html). ## Global impact The issue is still hotly [discussed](http://www.reddit.com/r/security/search?q=heartbleed) [all](https://twitter.com/hashtag/heartbleed) [over](https://news.ycombinator.com/item?id=7548991) [the](http://insecure.org/search.html?q=heartbleed&sa=SecSearch&siteurl=seclists.org) [web](https://www.google.com/search?q=heartbleed&tbm=nws) and it will take probably some time before the first panic subsides and an in-depth analysis can take place. Currently, only the worst case scenario is repeated about everywhere. This worst case is: Stolen private (SSL) keys. Leaked sensitive data (eg in a mail server context, that might be login credentials). If that's true, it would mean for everybody offering SSL (whether hosted on fortrabbit or about everywhere else) to swap their SSL key immediately. Also change about any password you used all over the net… from [ebay](https://twitter.com/TheBlogPirate/status/453496986462068736/photo/1), to [facebook](https://twitter.com/AdamTheAnalyst/status/453475673911218177/photo/1), to [lastpass](https://twitter.com/eddturtle/status/453463720857837568/photo/1), to — sadly — the [fortrabbit dashboard](https://my.fortrabbit.com). ## How we were affected As this bug affected the current stable versions of the OpenSSL library — we were affected as well. Our free SSL App URLs are implemented using NGINX, which uses the OpenSSL library. Also the ReSync tool was affected in the same way. We've patched our nodes, thanks to the very fast reaction of the Debian maintainers, throughout the night and at around ~5h (UTC), we closed the vulnerability on the last of our nodes. In addition: we're using Amazon's elastic load balancers ([ELB](http://aws.amazon.com/elasticloadbalancing/)) for custom domain SSL certificates. Amazon [announced](https://forums.aws.amazon.com/thread.jspa?messageID=535168򂬮) that those ELBs are (or were) [affected](http://aws.amazon.com/security/security-bulletins/heartbleed-bug-concern/). AWS is currently patching their whole infrastructure throughout the regions. By now most (all as far as we know) of the ELBs used by us are fixed. ## What you should do To give a good recommendation at this state is not really possible. Here is what we've done and you should do as well: Change all passwords, starting with critical ones (eg the fortrabbit dashboard, banking, mail, …). Change certificates: Better now then later. Be cautious whenever visiting any side using encryption (are they already patched?) in the next weeks. Calm down. ## What brings the future That's a big mystery. It mainly depends on how fast the different distributor will — and can — react. Especially in the context of hardware devices, for which vendors usually take longer to provide patches. And users take longer to implement them. From routers, to [heaters](http://www.hotforsecurity.com/blog/vulnerability-in-vaillant-heating-systems-allows-unauthorized-access-5926.html), to mobile devices — there is a lot of bad potential out there. In any case: I'm sure that it's not yet over at all. # Hello Teutonic CSS Source: https://blog.fortrabbit.com/hello-teutonic-css Created: 2018-08-02 Author: Frank Lämmer Tags: webdev > Teutonic CSS, an open-source CSS framework grown out of the stylesheet behind fortrabbit, and the thinking that shaped it. **TLDR; Check it our yourself: [teutonic.co](https://teutonic.co)** ## Why yet another CSS framework? I am the design guy here. My aim is to make fortrabbit look unique. In order to do so, I have developed the "fortrabbit.css" which is currently in use on the page you are reading. For future fortrabbit projects it needed further generalization and I also wanted some fancy new extras. First off, I needed use cases - think of HTML markup to develop the framework against. Those examples became a kind of documentation and specification. They even live in their own repo. It's like test-driven development for CSS. From there it was only a small step to open source it. Check out this [Medium post](https://medium.com/@frank_laemmer/yet-another-css-framework-6f5a9b142b43), if your more interested in my motivations behind it. ## Who is it for? Sophisticated web designers who care about design details. ## What's so special about it? It makes use of CSS vars (CSS custom properties), which enables great theming options. You can work with compiled CSS directly. It has multiple ways to display content grids, see my [Medium post](https://medium.com/@frank_laemmer/using-flexbox-and-css-grid-together-71b7f6e219a5) on why I am using Flexbox and CSS grid together. It uses modular scale for spacing and typography. It has unique form styles. And much more. ## How can I use it? You can just hotlink the CSS file and adjust it using CSS vars to your needs, this actually works quite well. Or you can get the source code and integrate in your own build process. The source is in SCSS — without any extras — so most systems can run the build out of the box. ## Why doesn't it use any PHP? Doesn't have to. It has less dependencies and is more open. The documentation is Jekyll and it get's build on GitHub pages. ## What's next? Teutonic CSS looks familiar to the styles you can see on these pages currently, just more versatile and clean. Teutonic CSS will be the groundwork for upcoming fortrabbit projects. It will also be further developed with that. I have quite a few ideas on how to enhance it. For now, I am happy about feedback and issues you might have. ## Where is it again? Hop over to: **[teutonic.co](https://teutonic.co)** # fortrabbit just launched in the US Source: https://blog.fortrabbit.com/hello-us Created: 2016-02-24 Author: Frank Lämmer Tags: changelog > fortrabbit opens a US East data center location for new apps, and adds billing in US dollars alongside the euro. ## Getting started **New users**: [Sign up](https://dashboard.fortrabbit.com/signup) & enjoy the smooth boarding. **Existing users**: can change the way you are billed on individual App level and data center location for New Apps: ### How to choose a data center for a New App ![us-data-center-location](/images/us-data-center-location.png) For any New App you create from now on, you will be asked for the location: 1. Login to the Dashboard 2. Hit the "Create an App" button 3. Choose an App name 4. Choose the data center location 5. … the rest follows as usual The data center location will not affect the currency, which is defined by the Billing Contact (see below). ### How to copy an App to a different data center Sorry, there is currently no automated way to clone an App to another data center location. But you can do that manually. The basic steps are as following: 1. Create a new App with the desired data center location 2. Add the new Apps repo as an additional remote in Git 3. Push the code to the new remote 4. Migrate your database (if you have one) 5. Test everything 6. Route DNS to the new App 7. Delete the old App Please also see our general [migration guide](http://help.fortrabbit.com/migrating) and the guide to [move from Old Apps to New Apps](http://help.fortrabbit.com/new-apps). Please don't hesitate to [contact us](mailto:support@fortrabbit.com). ### How to create a new Billing Contact with USD You currently cannot switch the currency "on the fly", but you can create a new Billing Contact with the exact same data — well, except for the currency, of course: 1. Login to the fortrabbit Dashboard 2. Go to "Your Account" 3. Select your desired "Company" 4. Hit the "Add a new Billing Contact" button 5. Fill out the forms — including currency: USD or EUR Please mind that we can only provide USD for non-EU countries — due to billing issues (VAT & MOSS). ### How to move your App to another Billing Contact to change the currency In order to have your Apps billed in another currency you can move them to another Billing Contact — the one you just created for example: 1. Login to the Dashboard 2. Navigate to the App you would like to move 3. Hit the "Change ownership" button 4. Choose the new Billing Contact Changing only the Billing Contact will only affect billing — no downtime, no team changes and no change in the data center location (of course). You will notice that the App will show up on two invoices of the current month: Up until now on the old Billing Contacts invoice, from now on the New Billing Contact invoice. Don't worry, that's expected. You won't be billed twice, the billing cycle is daily. Also see our [Billing FAQ](http://help.fortrabbit.com/billing). --- Still reading? You rock! Let's continue with some backgrounds and even more important details: ## What took you so long to come to the US? We get requests to bring our service to the US frequently. So we first passed the idea around already in [August 2013](https://web.archive.org/web/20130901223209/http://www.fortrabbit.com/feature/fortrabbit-goes-us). Along the way we decided to postpone this until our second generation of infrastructure becomes ready — as this new infra is much easier to maintain. The time has finally arrived. The New Apps have been tried and tested and became generally available in December. We have recently released the Worker Component and made PHP 7 available. Thank you for your patience so far. ## Why Virginia? We settled for the AWS data center US-EAST-1 for now as we see the most interest from the East Coast & Canada. This brings **performance gains** when your visitors are coming from all over the US. Data travels [by the speed of light](http://www.tested.com/tech/web/454189-blame-your-latency-speed-light/), but although light is really fast, it's a long way from here to over the pond — especially because it's not really a direct route. So there is a latency, which effects your page delivery. It actually affects your App more if it is faster: we are talking about 40-70 ms per request. So if your App is real fast and delivers requests to Europe in 50 ms it would be around 100 ms to the US. Twice the time. The more assets your website is using the larger the cumulative effect, of course. ### Other performance frontiers Please mind that many more factors will affect your Apps "snappiness": - frontend facing delivery optimization < CSS/JS/IMG - backend performance < MySQL slow queries … - Old App vs New App < I/O intensive New Apps are much faster - data center location < as mentioned above - PHP 5 vs PHP 7 < the later is much faster of course ## USD + EUR — side by side fortrabbit is for entrepreneurs only — B2B for the rest of us. That's why it is important to support all kind of combinations with the new possibilities: Clients from the States can now pay in their home currency: US Dollars are accepted via VISA or MasterCard (AmEx is under consideration). The data center of your App however is not linked to the currency. In this is a big feature: You can choose a currency (EUR or USD) with every new Billing Contact. This enables you to have Apps in the US & Europe and still pay in your home currency. Please also see our [collaboration article](http://help.fortrabbit.com/collaboration). ## 1-to-1 currency exchange rate for now Our aim is to simplify cloud quirks. Given the current situation, we decided to have a price parity for US and EUR — at least for now. That means that you can have the "PHP s 1" plan for €5 or for $5. This price is influenced by many factors. AWS offers different prices in different regions. Buying resources in the US-EAST-1 is more affordable. The most important factor however is of course the EUR/USD exchange rate. We have seen the Euro decline over the past three years, from 1.33 to 1.11 recently. This is tough, as it affected our business negatively already. Being paid in USD and paying (to AWS) We will monitor the situation and act accordingly — Price changes will communicated upfront of course. In general you can expect the prices to go down — as cloud computing resources come more affordable. Our recently introduced offer huge price drops by improving performance. But under certain circumstances we might need to adjust the pricing and difference between USD and EUR prices. ### Dealing with a foreign company While researching about US-EU business relationships I found about certain circumstances which will restrict US business to ask for a W-8BEN-E form when dealing with a foreign company (as we are). As far as I understand the situation now — this is not needed as we are an "active company". See my related [question on Quora](https://www.quora.com/Will-we-need-to-fill-W-8BEN-E-to-do-business-in-the-US-as-a-foreign-company). ## Minor updates to TOS In preparation to this, we have reviewed our legal documents. We did some minor — cosmetic — changes to the TOS, SLA and privacy pages. The new TOS apply to all new clients. Existing clients can opt for the old TOS. I know, nobody reads those. But we would like to be as transparent about this, so we published our legal docs in Markdown on [GitHub](https://github.com/fortrabbit/legal). Changes are "diffable" and all changes have detailed commit logs. --- Hey brave all-the-way-to-the-bottom-reader (or -scroller), you came a long way. Why don't you leave a comment? # Hello world! Source: https://blog.fortrabbit.com/hello-world Created: 2012-06-15 Author: Frank Lämmer Tags: chronicles > The first post on the fortrabbit blog, announcing a next-generation PHP platform built in Europe, and what this blog will be for. Hurray. You have not reached the end of the internet. You have discovered something even more joyfull: **The official Fortrabbit Corporate Blog**. We are building the next generation PHP platform for Europe. Here we are going to write about things that matter to us and hopefully also to you. Informations about: Cloud Hosting, PHP Deployment, AWS setups, Startup, Bootstrapping and maybe sometimes about our products. # A web hosting control panel with a social network you say? Source: https://blog.fortrabbit.com/hosting-panel-with-social-network Created: 2024-10-11 17:32:51 Author: Frank Lämmer Tags: chronicles > Why a hosting dashboard gets collaboration features that look like a small social network, and what agencies and freelancers do with them. We aim to provide a different kind of web hosting with a 'hosting platform', not just a 'hosting control panel'. Our current hosting dashboard already includes collaboration features. It helps startups, agencies and freelancers to map their real world business relationships, so they collaborate with each other and their clients. We know that these features are used and appreciated. Many other hosting providers have also integrated similar functionality by now. So for the [new platform in the making](https://new.fortrabbit.com/) I explored how to improve those existing collaboration features and solve some quirks and shortcomings along the way. It became a big undertaking. Foremost, the data structure had to change. I replaced most top down hierarchy with many-to-many relations for extended flexibility. There are only four kind of objects: people in relation to apps, teams and payment methods. Make it powerful but not complicated. It took various attempts to get it right, conceptually. One approach had some unexpected side effects: changing billing should not change developer access. Another one was too leaky: Imagine an open social graph to browser the apps of the colleagues of your colleagues. Another challenge was to settle with restriction levels for the roles with the teams. What is allowed and what not? Can our tool help to prevent damage done by incautious junior developers or unaware clients? It turned out that even the lowest kind of possible access level implies that people collaborating with each other also need to trust each other. It's impossible to make it bullet proof. We don't want to ship something that only pretends to be secure. We ended up with a open solution and only two simple team roles. Our solution should enable people to collaboratively create. I hope it will feel familiar for existing customers. Hosting is about technical stuff, but also about people. Your account is your personal access to the platform. People can be part of multiple developer teams with different roles. Payment methods are owning the apps, they are managed by people. You will be able to invite others as solo developers to specific apps, or to one of your teams to participate on all or even just some selected apps. You can invite someone to a payment method or to take over billing. Non-technical clients have access to a slimmed down dashboard, excluding technical details. People can also request to get access on objects. Building this isn't easy either. Our internal collaboration project for initial release is taking much longer than expected. I filed countless bug reports and we are not fully done yet. Overengineering? Certainly. 🚩🚩🚩 # Performance / convenience Source: https://blog.fortrabbit.com/hosting-performance-hosting-convenience Created: 2013-07-10 Author: Frank Lämmer Tags: opinion > Hosting is still argued over price and performance. The case for judging it by convenience instead, from a PHP platform startup. One of the greatest challenges our PHP PaaS startup is facing is not a technical one: We need to change the way people think about hosting. Today there is still too much attention on the performance / price ratio. Think different. Of course i browse [Hacker News](https://news.ycombinator.com/news) for fun. But it is also a good source to learn about our target audience with lots of threads about PHP and hosting. Some days ago there was [a discussion](https://news.ycombinator.com/item?id=5978364) about [an article](http://remcobron.com/cloud-server-review-and-comparison-amazon-aws-ec2-vs-linode-vs-digitalocean/) by Ronald van Woensel. He compared the performance of three hosting services: Digital Ocean, Linode and Amazon Web Services. Most of the comments discussed the quality of the benchmarking and other services that were missing in the list. I posted: My two cents here: Benchmarking is all fine, but from my point of view, the performance-price-ratio is not sooooo important in hosting. This discussion reminds me of PC customers buying behavior in the 90ies. What's better AMD or Intel? ... Nowadays other features are key: What's the weight of this device? How thick is it even? Apple has changed the way we look at these things today. Convenience also matters in hosting a lot. How much time do i have to spend to have my app up and running? Do i really want to set up and maintain everything myself? How good is the support? Do i want just bare metal computing resources or a solution provider with an eco system? What matters the fastest server ever, when your queries are slow (because of poor design)? The performance of any app/website relies heavily on the engineering skills of the developers. See caching, see i/o load, see frontend technologies, see page load. It is easy to say that AWS just sucks and is overpriced. Think again, what is AWS really charging for? What does it cost to develop and maintain a website compared to what it costs to host a website? Are [virtual private servers or containers](http://www.linuxjournal.com/content/containers%E2%80%94not-virtual-machines%E2%80%94are-future-cloud?page=0,1) the future of the cloud? Another example: Is horsepower still so important to you when buying a car? What about design and fuel consumption? Do you need your own car at all? Maybe car sharing is an alternative? # How to detect and fix a hacked PHP website Source: https://blog.fortrabbit.com/how-to-detect-and-fix-a-hacked-php-website Created: 2026-01-07 09:27:09 Author: Frank Lämmer > Spot signs of a hacked PHP website, clean infected files, restore from backup, and lock things back down. ## Common patterns Got pwned? It happens often. A hacked PHP website is rarely a targeted attack — most are script kiddies chasing quick wins and a few bucks. Automated attacks usually leverage known vulnerabilities in unpatched software. - Phishing sites for banks and crypto wallets - Crypto mining - Fake e-commerce stores - SEO spam - sneaky links to shady sites - Malware distribution to your visitors - Backdoor installation for later use - DDoS participation ## Target systems Hackers love PHP‑based websites. Server‑side rendering lets them execute code; with weak isolation they may even escalate privileges. These are the systems we most often see targeted: - WordPress - WordPress - WordPress - Craft CMS - Laravel - Others ## Detect a hacked PHP website A hacked PHP website usually announces itself in one of these ways: - Performance problems - Website errors (500, 504 …) - Strange Google results - Unexpected content on the website - Google blocklist warnings - Phishing warning on the website - Weird new users in your admin panel - Your friendly web hosting service notifies you - A CVE is discussed online In our experience, the average time to detection is about three months. Some catch it quickly, others snooze. ## Implications - SEO ranking downgrade - Cached search engine results with spammy content - Higher hosting costs ## Investigate Check the access logs to see which files have been accessed how and by whom (by IP) to get a better picture. ## Fix a hacked PHP website The fix depends on how deep the intruders got in. Sometimes it helps to investigate recent breaches. The more you know about the attack, the easier it is to find a cure. ## Is the hosting runtime compromised? VPS hosting systems are at risk of full compromise. Many hosting providers, such as ourselves, provide a jailed environment where it's unlikely that hackers can escalate access beyond the website owner. If in doubt, rebuild the hosting resources (after creating fresh backups) and redeploy to a clean instance, or reinstall the OS. fortrabbit users run in a tightly jailed environment making it extra hard to escape. ## Restore from backup Preferred path if you have recent, trustworthy backups. Backups can be local copies of your development environment, a hosted Git repository, or the backups provided by your hosting platform. For classical LAMP‑stack applications, backups usually include the code, runtime files like uploads, possibly build artifacts, and a database dump. Restoring from backup means redeploying the code and importing the database dump. ## Cleanup No backups? Clean up manually. Download all online code to your local environment so you can work faster and make safe mistakes. Use grep and friends to hunt for trouble. Your AI can probably help you detect obfuscated PHP. You can also compare your framework or CMS core files with clean upstream versions to spot modifications. - Run `composer audit` in Composer driven projects - Clean files - Look deeply, backdoors can be hard to detect - Search for obfuscated code between normal code - Look in usual locations - Files with weird timestamps - Hidden files with names like `.htacces` (missing s) - Obfuscated PHP, base64 blobs, eval and assert scattered around - Clean database - Check users and roles for unknown accounts - Scan posts/pages/options tables for injected links or iframes - Look for serialized payloads hiding scripts - Export to SQL and grep for suspicious keywords ### Example files Here are some files from a recent [Craft CMS CVE](/craft-cms-cve-2025-32432) that we found to be affected. ```bash .well-known/* .widgets.php accesson.php autoload_classmap.php cgi-bin/* CoreCheck.php craftt-api.php envcraft.php m.php memberfuns.php mn.php mnb.php wp-blogs.php # Some files might be deeply hidden with existing folder structure like so: assets/_120x78_crop_center-center_none/-vwugcm.php assets/_240x122_crop_center-center_none/-gqpmnb.php assets/_68x56_crop_center-center_none/-yuobgf.php cpresources/4c4d6e37/d3-format/-rfihgs.php cpresources/718fe862/mode/cypher/-nswipf.php cpresources/718fe862/mode/swift/-oxtkip.php cpresources/926d5982/js/captchas/-wtfbav.php cpresources/d87ff9ec/-npcqfu.php migrations/... templates/... vendor/... ``` ### Example code Obfuscated code is meant to be unreadable for humans. It's usually encoded. Luckily, the code of your CMS or PHP framework is not obfuscated, so identifying malicious code is not that hard. ```php // Harmful code sometimes is hidden between other code. Read, search, ask — how to write a support request that gets a useful answer quickly, and what makes hosting support slow down. ## Do this ### Read, Search, Ask Consider the following pattern when you have a question: 1. **Read** - Our [documentation](https://help.fortrabbit.com) covers all general topics 2. **Search** - See error logs, check Google & Stack Overflow 3. **Ask** - Haven't found an answer? Ask us! This is the most time-efficient way to handle being stuck, and it's the most respectful of other people's time, too. And it helps you, to get up running faster on your own. [See a post about this pattern](https://medium.freecodecamp.org/read-search-dont-be-afraid-to-ask-743a23c411b4) established by freeCodeCamp. ### Provide context and details The more we know, the better we can answer. Please don't make us guess or query you back for details. A good report may contain: - I have tried to: "…………" - I do so because: "………" - I expected: "………………" - The error I see is: "…………………" - This is the verbose output of the error: "…………………………………" - My setup is "…………" - It works locally: "yes/no" - It happens all of the time: "yes/no" - It worked before: "yes/no" - It affects all of my Apps: "yes/no" - I have also tried this alternative way: "………………" - I have also tried this workaround: "………………" ### Tell us who you are With fortrabbit [an Account is a person](https://help.fortrabbit.com/account) — not a [Company](https://help.fortrabbit.com/company). By providing your name, conversations are getting more personal. With longterm clients we have 100s of conversations and 1000s of replies. We'll get to know each other. This is a relationship. ## Avoid this ### Ping pong games ![Support 1 - ping pong](/images/support-01.png) Modern customer support systems, like [Intercom](https://www.intercom.com/) or [alike](https://www.producthunt.com/ask/1829-which-is-the-best-and-free-alternative-to-intercom-io) are chat based. **Your questions are getting conserved and we'll come back on you ASAP**. So like e-mail the conversation doesn't have to happen in real time. Avoid pleasantries and greetings, just be on point and ask right away. _"Hello, you there?" "Hello anyone?" "Hello?"_ ### Not a real question ![Support 2](/images/support-02.png) Make sure to ask a question we can answer. What kind of answer do you expect for "Something is not working"? ### Lazy call ![Support 3](/images/support-03.png) Our [extensive help pages](https://help.fortrabbit.com) should give you a good overview on how to get started. You'll find our quickly if fortrabbit is for you. Invest in your question and we'll invest in the answer. ### Fuzzy question ![Support 4](/images/support-04.png) Imagine your car is not starting. You call up your mechanic and just tell him that. Do you expect a solution right away based on the limited information you provided? Writing a good question requires some efforts on your side. But that will force you to overthink your problem. In many cases you'll find a solution yourself when thoroughly thinking about the question. Based on sufficient information we are likely to find an answer faster and better. --- > ASCII stupid question, get a stupid ANSI! --- ## Good to know General client support here is free of charge — we both profit from this! Your questions and feedback helps us understanding your needs and obstacles you might have. Support is officially limited to office hours, but in most cases we answer much faster. Our aim is to give you a good technical support and help you getting your PHP Apps up and running here. # How to keep a secret Source: https://blog.fortrabbit.com/how-to-keep-a-secret Created: 2015-09-08 Author: Ulrich Kautz Tags: webdev > Passwords in git are bad and environment variables are not perfect either. Where application secrets should actually live. ## Is your database password stored safely? How do you protect your access data? Your sensitive secrets, basically anything your PHP application uses to authenticate or authorize with other services such as databases, caches, cloud storages, image resize services, transactional mail providers. All of them. Where do you put this — easily accessible while in development and secure for production? ## Not in Git The first thing we can agree on is, that you will not store your secrets in version control (in a `config.json` file) — they will stay in there forever and they are exposed: `git log --follow -p -- config.json`. Why is that so bad? Because your never know what happens in the future: Who will have access to the code base? A VCS, by it's very nature, keeps everything in it's history. So even if you remove the credentials later on, everybody will be able to look them up in the history. Also, given multiple developers, not everybody needs to know the credentials, so they should not know the credentials. ## Not in an ENV var either? We see a trend in storing secret credentials in environment variables. I think this is rooted in the Ruby world somewhere around the [12 factor App principles](http://12factor.net/config). That way your Git repo is clean and you can easily switch between environments and it's super smooth to run multiple stages of your App by just configuring the ENV vars accordingly. **But for sure, it's not secure**: Environment variables in PHP are possibly exposed to public: ![](/images/phpinfo-envvar.gif) During development one often creates a [phpinfo](http://php.net/manual/en/function.phpinfo.php) to check if changes in PHP settings have applied or which extensions are installed. Mind that this dumps all of your ENV vars including key and value. That's an bigger issue as you might think, because sometimes a phpinfo is there without you even knowing about it: The [Symfony Web Debug Toolbar](http://symfony.com/blog/new-in-symfony-2-8-redesigned-web-debug-toolbar) and the [Laravel debugbar](https://github.com/barryvdh/laravel-debugbar) come with a handy phpinfo out of the box. And if it's not a `phpinfo()` call, then it's one of the myriad of other development supporting tools, which will also dump environment variables with a glee. Now imagine that your App is already online during development, or one of those dumps is just temporary online, for a quick fix and now the Google bot comes along and happily gathers all those information. Now some weeks or month later, someone else finds it in the Google cache - or archive.org - or something akin. That will be a sorry day for you. Remember: The Internet does not forget (and in this case: does not forgive). ## A proposal Let's remind ourselves that [saving passwords in plain text isn't secure in any case](http://stackoverflow.com/a/12461680/1449386). But maybe we can take two bad practices and turn them into one good: 1. Create a secret key, which you store with the code of your App 2. Store the encrypted credentials in env vars This gives you the advantages of both: Your credentials are exposed to nobody: Even if the environment variable are accidentally dumped they will make no one any wiser. You still do not store the actual credentials (or any way to derive them) within the version controlled code. ### Example Following an example how to use the proposed pattern with Laravel 5.1. Start with creating a new secret key, which will be stored with the code of your App: ```bash $ php artisan tinker >>> \Illuminate\Support\Str::random(16); => "7mnYhyVASN717Mi9" ``` Store this encryption key in a new config file, eg `config/env.php`: ```php '7mnYhyVASN717Mi9' ]; ``` Now you need to encrypt all the environment variables you want to protect (passwords, secrets, ..). You can do this either using tinker, or, if you plan on repeating this from time to time, create a new Laravel command. Here is [an example command](https://gist.github.com/ukautz/5f9b7fca62bfaead886b). Following the tinker-way: ```bash $ php artisan tinker # create encrypted instance with your secret key >>> $c = new \Illuminate\Encryption\Encrypter(config("env.key")); => Illuminate\Encryption\Encrypter {#765} # encrypt your plain text values and prefix them with "ENC:" >>> "ENC:". $c->encrypt("Some Value"); => "ENC:eyJpdiI6InJUR2kyc...Q3In0=" >>> "ENC:". $c->encrypt("Another Value"); => "ENC:eyJpdiI6IkdcL2ErRW...ifQ==" ``` Since you want to use the decrypted environment variables in the various `config/xyz.php` files, you need to do the decrypting early in your bootstrap process. Add the following code example at the very top of `app/bootstrap.php`, above any other code: ```php $env = require __DIR__. './../config/env.php'; $crypt = new \Illuminate\Encryption\Encrypter($env['key']); $secEnv = []; foreach ($_SERVER as $key => $value) { if (!is_array($value) && strpos($value, "ENC:") === 0) { $secEnv[$key] = $crypt->decrypt(substr($value, 4)); } } function secEnv($name, $fallback = '') { global $secEnv; return isset($secEnv[$name]) ? $secEnv[$name] : env($name, $fallback); } ``` Now you can use `secEnv("ENV_NAME", "fallback value")` anywhere, to access your encrypted values. Eg in your `config/database.php`, you can write: ```php // .. 'connections' => [ // .. 'mysql' => [ // .. 'password' => secEnv('DB_PASSWORD', ''), // .. ], ], ``` ## Convenience VS security We run this slick hosting platform, you know. Developer happiness is our ultimate goal. We avoid proprietary solutions in favor for familiar and compatible tools and workflows. From that point of view, automatically storing plain text credentials in ENV vars is very tempting. It's easy to get started, apps are portable and it just feels good. Some of our competitors do so, without pointing out the risks. With fortrabbit instead passwords (MySQL and SSH) are only shown once after creation and then we do not store them in any restorable (or re-viewable) way. So we do nothing wrong. But what are the users to do then with those credentials. And what do they do with their "other" credentials? Think: their AWS secret key or the like. We spoke to some and it turned out that some were unaware and used unsafe practices. So far we see two options to improve the way we provide "our" credentials: 1. A mandatory proprietary solution (such as a credential file): save, but certainly not convenient and it does help naught with the "other" credentials 2. Credentials in ENV vars as a "factory setting": easy to get started. Then nag about better solutions, until everybody feels bad if they don't do it. Currently we're strongly leaning towards the nagging, since we like to do that and it will provide a better understanding of the underlying problem. It will educate and thereby improve overall security. It will provide a solution for the "other" credentials as well. ## Further readings For completeness sake it might be mentioned here that our [Old Apps](http://help.fortrabbit.com/old-and-new-apps) also allow SSH access on a persistent storage which makes it possible to store a config file without having it in Git. Our [New Apps](/new-apps-are-here) instead have Git-only deployment and ephemeral storage, which makes an even more current topic for us. In our previous post about the [10 PHPillars](/10-pillars-php-dev) we promoted the idea to separate configuration from code (showing ENV vars instead of plain passwords), but did not elaborate on the way the credentials should be stored. Now we extend on that and propose a solution on how to do it even more safely. The article [Environment Variables Considered Harmful for secrets](http://movingfast.io/articles/environment-variables-considered-harmful/) by Michael Reinsch and the following [discussion on HN](https://news.ycombinator.com/item?id=8826024) are also worth checking out. Thanks for reading so far! Now, whats your opinion? # Deploy to fortrabbit with GitHub Actions Source: https://blog.fortrabbit.com/how-to-use-github-actions Created: 2019-11-19 Author: Yann Rabiller Tags: webdev > GitHub Actions arrives, and fortrabbit gets a deployment workflow built on it — useful when the built-in git deployment is not enough. 2026-03-17: We have an updated GitHub integration with more recent details here: [docs.fortrabbit.com/integrations/git-providers/github#example-deploy-via-rsync](https://docs.fortrabbit.com/integrations/git-providers/github#example-deploy-via-rsync) ## Why bother? fortrabbit already has Git and even Composer build in without the need of any extra service. But fortrabbit currently does not offer a Node.js runtime during deployment, so common build tasks (Webpack) can not run here. So, one good use case to implement GitHub Actions is to automatically build static assets, like and JS, CSS. Or you can test and do other advanced stuff before deploying to fortrabbit. ## The goal For now, let's build a prototype to deploy code to GitHub to trigger a simple JavaScript build process and automatic deployment to fortrabbit afterwards. ## Get ready You will need to generate an SSH key to allow GitHub to access your fortrabbit App. Start in the Terminal of your local computer (not the fortrabbit App): 1. Create a key pair: `$ ssh-keygen -t rsa -b 4096 -m pem -f /tmp/key-github`. This will generate two files: `/tmp/key-github.pub` and `/tmp/key-github`. The first one is the public key, the second one is the private one. 2. With the [fortrabbit Dashboard](https://dashboard.fortrabbit.com/), go to your App and add an **App-only SSH key**. Paste the content of the public key. This will allow anyone or any app having the corresponding private key to access this app. 3. On your GitHub repository, go to the Settings, and then go to Secrets. There, add a new secret, call it `SSH_PRIVATE_KEY` (if you want to follow our example, but you can obviously call it as you want), and paste the content of the private key. 4. Now you don't need the keys in your local `/tmp` folder anymore and you're all set up. ## Two methods We will show two ways to integrate GitHub actions, both can have the same result, but the approach is different: ### 1. Git transport layer method Available for Universal and Professional Apps. Here, you commit all files, including the uglified JS, inside the CI's temporary Git repository, then force push to deploy. You can use this example workflow YAML as a starting point: ``` name: Deploy through git on: [push] jobs: build-and-deploy: env: GIT_EMAIL: GIT_USERNAME: REPO_URL: REPO_BRANCH: runs-on: ubuntu-latest steps: # This will pull the github repository to the current pipeline - uses: actions/checkout@v1 # This will automatically set up ssh with our private key - uses: webfactory/ssh-agent@v0.5.4 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} # Use the version of Node.js you need - name: Use Node.js 10.x uses: actions/setup-node@v1 with: node-version: 10.x # If you need node dependencies and to build some js/css - name: npm install and build run: | npm ci npm run # If so, you can then remove the source assets folder - name: Remove the source assets files run: 'rm -Rf ' - name: Configure Git # The local git needs a user to be configured to commit & push run: | git config user.email $GIT_EMAIL git config user.name $GIT_USERNAME - name: Commit everything (with new built assets) # You can also specifically "git add public/your/path" run: | git checkout $REPO_BRANCH git add -A git commit -m "Build $($CURRENT_DATE_TIME)" env: CURRENT_DATE_TIME: "date +%Y-%m-%d:%H-%M" - name: deploy run: | git push --force $REPO_URL env: # This avoids a failure when the client does not know the SSH Host already GIT_SSH_COMMAND: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" ``` As you may have noticed, we don't install PHP dependencies here, because when a Git deployment happens with fortrabbit, a Composer install is automatically triggered. ### 2. rsync transport layer method Only available for Universal Apps. Here we will use `rsync` to deploy to fortrabbit at the end. Instead of dealing with a temporary Git repository in the CI that you alter, you can directly send all the files through rsync. ``` name: Deploy through rsync on: [push] jobs: build-and-deploy: env: DESTINATION: "" runs-on: ubuntu-latest steps: # This will pull the github repository to the current pipeline - uses: actions/checkout@v1 # This will automatically set up ssh with our private key - uses: webfactory/ssh-agent@v0.5.4 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} # We decide to use Node.js 10 here (could use 8, 10, or 12) - name: Use Node.js 10.x uses: actions/setup-node@v1 with: node-version: 10.x - name: Validate composer.json and composer.lock run: composer validate - name: Install dependencies run: composer install --prefer-dist --no-dev --no-progress --no-suggest --optimize-autoloader --ignore-platform-reqs # If you need node dependencies and to build some js/css - name: npm install and build run: | npm ci npm run # If so, you can then remove the source assets folder - name: Remove the source assets files run: 'rm -Rf ' - name: deploy # The StrictHostKeyChecking option avoids a failure when the client does not know the SSH Host already run: | rsync -azh -e 'ssh -o StrictHostKeyChecking=no' ./ --rsync-path='rsync' $DESTINATION:~/ ``` A Composer install in GitHub's CI is triggered. Since the fortrabbit Git repo stays untouched, hence no Composer process will be launched on the deploy service. Everything will be transferred to fortrabbit already packed. ## Feedback please Please let us know what you think! We are actively considering different implementation ideas. What would you prefer: Having Node.js directly integrated with our service without the need to use an external service for this, or better integration with GitHub (and/or maybe BitBucket and others)? What do you think about the two approaches outlined above? Do you fully understand the differences? What would be your setup? Maybe, what's your use case? ## Thanks to our smart clients We have mentioned this many times before, but we really do enjoy having such smart clients, constantly requesting features and producing edge cases. It helps to shape and build our services. This blog post and the actual prototype was heavily inspired by [diesdas.digital](https://diesdas.digital/)! # How we do transactional e-mails Source: https://blog.fortrabbit.com/how-we-do-transactional-mail Created: 2017-06-22 Author: Frank Lämmer Tags: chronicles, webdev, opinion > Our real-live practices on auto-generated client e-mail communication. ## Tech ### Composer package / micro-service We like separation. So the fortrabbit transactional e-mail project is living in a separated (private) Git repo. It contains the actual e-mail contents in form of Twig templates as well as integration code (Laravel provider) and a small toolset for building and sending the e-mails for tests. ### Testing the e-mails ![Sending a test-mail from local](/images/transactional-testing.png) There is a test-suite — complete with dummy data — that enables us to quickly send test-mails from a local machine. This helps seeing changes to the HTML template design and finding broken links and typos. We do this locally, some of our clients are using [Mailtrap](https://mailtrap.io/) for email testing on staging sites with us. ### Twig templates ![Twig template](/images/transactional-twig-template.png) The screenshot shows part of the HTML template. ### Markdown to HTML ![Markdown example](/images/transactional-markdown.png) HTML e-mails get more attention. A good e-mail should include a HTML and a plain text part. To avoid to edit the same e-mail twice (html + plain text), we are writing simple e-mails in Markdown. This renders nicely to HTML and plain text.

Call to action with micro data

![email markup example](/images/transactional-email-markup.png) Most transactional e-mails contain a CTA link like 'accept invitation', 'invite your client' or 'download your invoice'. The actions are defined at the head of the template. Some extra JSON markup is enriching the parsability of the e-mail. We are using [email markup (Google)](https://developers.google.com/gmail/markup/reference/formats/microdata) here. Currently this only works with the Gmail web client. ### Domain configuration We have configured the domain with DKIM and SPF for enhanced security and to assure that our mails will arrive the inboxes. The receiving mail server can safely identify us. ### Sending mails with Postmark Transaction mails are time-sensitive. Imagine your double-opt in e-mail never arrives and your clients are hanging in a dead end street. That's a missed sale. So, instead of maintaining our own mail server or misusing a standard mail server, we are happily spending a few extra bucks on an outbound e-mail service. In our case this is **[Postmark App](https://postmarkapp.com/)** from Wildbit (no association) — we used it from beginning on and we are very happy with it. ![Postmark screenshot](/images/transactional-activity.png) A bonus on top is the activity list in the Postmark dashboard. Here were we can see and search for individual e-mails, which also helps in debugging and resolving support cases. Postmark is not the only provider for Transactional mail as a Service. ## Communication We try to be as concise as possible in design and content. ### Simple and short e-mails > If I had more time, I would have written a shorter letter. I don't know about you. But I only have very little attention when it comes to a double-opt-in e-mail. Where is the thing? Where is the button? I am hardly reading any text in there. So, our transactional mails are a as short as possible, mostly just one sentence, just one column, one or two clear call to actions. ### pleasereply instead of noreply Instead of a standard `noreply@fortrabbit.com` e-mail addresses we are using `pleasereply@fortrabbit.com` as the sender. People have questions on those e-mails, they naturally want to reply and they should be able to. Those e-mail answers will end up in our centralized ticket system. ### A personal touch ![Signature](/images/transactional-signature.png) The fortrabbit mailbot doesn't pretend to be human. A human (not an AI) will answer on reply. ### Transactional and retention The line between marketing and information can be thin. We are strict about this: - **Transactional emails are informal** — 'password reset', 'invoice notice', … - **Retention emails are sales**: — 'long time not seen', 'have you seen X?', … Our aim is to send only essential e-mails and not to SPAM our users. But in terms of retention, we are probably sending far to less mails. E-mail is powerful tool when it comes to activation and boarding of users. ### Timing & combination A tricky - yet to be solved - part is: to send the right e-mail at the right time to right user. Beside our own engine here, we are using external services for newsletter (think [Mailchimp](https://www.mailchimp.com)) and direct client communication (think [Intercom](https://www.intercom.com)). All those channels end up in the users inbox. They look differently and are coming from different sources. Still they should add up to ONE streamlined communication with the client. ## Design ### Style generation ![Gulp task to create the styles](/images/transactional-gulp-task.png) Our transactional mails are part of the fortrabbit identity — this is a living thing and should always be up-to-date. The style-sheets are getting build from an external Gulp build script, which itself is part of the fortrabbit style framework — the master style. For compatibility reasons, the CSS is part of the HTML mail itself. So each e-mail contains a fair amount of CSS. Sounds very fancy, is actually quite useful and fast. ### Progressively enhanced HTML/CSS styling ![Fallback rendering](/images/transactional-fallback-rendering.png) Not all e-mail clients out there are supporting the latest CSS3 features. So in order to have your HTML e-mail displayed nicely even in an old version of Outlook you have to use very basic HTML and CSS styling and quite a few hacks — read: 90ies style table-layout. There are even e-mail frameworks (like [mjml](https://mjml.io/) or [Foundation Email](https://foundation.zurb.com/emails.html) or ) out that out there. I decided to use just very basic styling that will degrade nicely (mostly) when certain features are not available. I haven't tested it hardcore across e-mail clients. I guess that our target audience has newer clients. Half of the Account e-mails are by `someone@gmail.com`. I assume that most are using the webmail client. --- This is the bottom. Thanks for reading or at least scrolling so far! # How we estimate hosting resources Source: https://blog.fortrabbit.com/how-we-estimate-hosting-recources Created: 2013-08-23 Author: Ulrich Kautz Tags: webdev, opinion > How a hosting provider turns vague expectations into concrete plans: the Map your App decision helper and the reasoning behind it. We've recently upgraded our fortrabbit.com website, including a complete overhaul of our [pricing visualization](http://fortrabbit.com/pricing). The visualization is one thing, the other is our [Map your App](http://fortrabbit.com/pricing/wizard) decision-helper: One of the major problems all hosting providers have to solve (or should at least try) is to make it transparent to the customer what kind of resources she needs. ## Tell us your story, please Well, the major problem is that no two web applications are the same. Even if they are based on the same technology stack, say framework XYZ, their actual resource requirements can differ widely. So, to tell you what resources you need, from a hosting provider perspective, requires a deep understanding of the inner workings of your App. Just to name a few: - What PHP technology stack it's build on? Eg framework X or CMS Y; - What other technologies are employed? Eg database, image transformation, PDF generation; - How are those technologies used? Eg PDF generation for once-a-month reporting vs on-demand, possibly every minute or even second; - How does the resource usage scale with more visits/requests? Eg each request thumbnails an image vs once a day; - How do visits translate to (PHP) requests? Eg an REST API where every "visit" is a request vs a media-heavy CMS in which each visit creates multiple requests; - Is caching used, to what degree (eg about everything vs "this one expensive query") and by what measure (eg file vs memcache vs database vs ..) This is of course not all (far from it), but you probably get the point: It's about impossible for us to tell you what resources your App will need when we don't know what you are actually doing. And we need to know this quite detailed and of course in the foreseeable (and beyond) future. ## Or don't? Is all that really necessary to know? We'll, actually it isn't. What it boils down to are two factors: 1. How long does your App need on average to render (milliseconds)? 2. How many visitors do you have? Ok, there are two more: _how expensive is it in terms of CPU_? However, this is only a (relevant) factor if you do stuff like image transformation or so. However, if this really is an often performed operation, it should not be done in the web part of your application anyways (that's what workers or third party image transformation APIs and so on are for). Then there is _how much memory does your application require_, especially in terms of APC usage, as we offer different sizes with our plans. ## Simple math First step is to take the amount of visitors, applying a simplified standard distribution over the day and determine the peak amount of total requests per hour. With the average render time per request, you can now get to the estimated amount of required parallel running processes. And that's about it. ## Even simpler As the whole estimation is - well - an estimation and the purpose is to give you a reasonable prognosis on what you will need, we can factor in our experience. So we defined three "sizes" and named them _slim_, _average_ and _fat_. Each size implies an average render time and is expressed through examples of underlying PHP technologies, to which you can relate. From our experience, the used PHP technology and the actual render time are strongishly*related. (*Yes, it's not impossible to build an App using [Slim Framework](http://www.slimframework.com/) which renders in minutes, not milliseconds, but it simply does not happen all that often) Finally, what we need to know is how many visitors do you expect and can give you a reasonable realistic estimation what resources you'll need. The only thing we need to know additionally are "special requirements", such as whether you want to use SSL or not (can't simply not be deduced from the above). ## Factoid? Fact? As you might have noticed, I somewhat overused the word _estimation_ here. The thing is: the at the beginning stated concerns are valid non-the-less. As a hosting provider, we can only speak in averages and a specific App could easily deviate from those averages. Let me put it this way: the bigger the deviation, the smaller the probability. A Symfony App, which we consider _average_-size, could surely render slower and need more resources in every aspect than an normal sized Mangento shop, which we consider _fat_. Still, it's just not very likely to happen often. ## You are up So, to help us make our estimations become true, we recommend to get familiar with our [App design and optimization guide](http://fortrabbit.com/docs/in-depth/app-design-and-optimization). Good application of caching can make a _fat_ App render like an _average_ or even _slim_ \- at least where it matters: on the visitor side. Leveraging storages, such as S3, can reduce I/O for media-heavy Apps vastly and reserve your App's fortrabbit resources for PHP processing. And that's just the tip of the iceberg. In the end, we are in this together. # How we hire Source: https://blog.fortrabbit.com/how-we-hire Created: 2025-01-10 10:53:08 Author: Frank Lämmer Tags: chronicles > Hiring at a small company without an applicant tracking system or a hiring manager, and the things that end an application early. ## Our current application tracking flow I track applications manually. No ATS, just a Notion database with a form. - [fortrabbit careers](https://fortrabbit.notion.site/) There is no hiring manager here. I look at a profile for a minute to make a quick decision on too little facts. It's manual labor thus and error prone. About 2% get invited for 1st interview. 33% of those will make it to the 2nd interview. Bad feeling when I have to reject candidates. We currently advertise on Indeed, LinkedIn and Symfony Jobs. Smaller job boards are preferred, less applications, but much higher quality. ## Cheating flaws everything Most applications are missing personal touch. The candidates seem to be good at a variety of skills making them look like the perfect match for almost every job offer. I understand the thinking, it may help higher chances to get accepted for any kind of random job. Yet. Of course, my job as the hiring manager, is to smell that something isn't right. Human intuition tells me that people can not be that good at such a board range of skills. Specifically I hate result driven driven language (quantify your impact on business outcomes). Phrases like this are almost certainly a cause of rejection: - reduce release cycle times by 75% - increasing monitoring efficiency by 30% - increasing site traffic and sales by 25% - leading to a 40% reduction in transaction processing time - boosting operational knowledge by 10x - expanded country support by 50% - cut dashboard load time from 20 to 2 seconds - achieving a 99% timely alert rate for critical updates - boosting data accuracy by 40% - significantly contribute to company revenue growth of over 300% - resulted in a 10% rise in new user registrations - increased release frequency by 50% - increased platform inquiries by 15% - the platform experienced a 25% increase in product views - resulting in a 40% increase in user registrations I found that this is not only bullshit language, but also very likely just SCAM. There are AI services ([Teal](https://www.tealhq.com/resume-examples/backend-developer#senior-backend-developer), [JobScan](https://www.jobscan.co/)) helping you to create such generic job applications. Basically, weaponize your CV. I guess those services are targeting application tracking systems that are using AI to scan and pre-filter CVs? Fine. What a great time to be alive. ![Very similar CVs](/images/similar-cvs.png) Some people even go the lazy route and don't even care to create individual CVs and just copy example text into their own CV. ## My reaction I feel tempted to analyze how many applications we got are cheating, but I better don't waste my time with that. It worries me. I like the internet as place to meet people and also to make business with strangers. Business requires trust in your business partner. All the applications using AI generated answers and fake CVs are creating a scene of mistrust. At best, I'd like to be open about new applications. I don't want to judge people from where they come from. Yet. After looking at 100s of applications my brain automatically recognizes repeating figures. Pattern recognition is hardwired in humans and helps us to survive. As a result I resort to pre-justice and social profiling. Applications from certain channels and countries have higher SCAM and bullshit levels. ## Tips to get an interview here - Have nice profile picture - Include links - StackOverflow link with relevant answers - GitHub profile with stuff to look at - Meaningful OSS contributions - Keep it short - Don't repeat yourself - Be honest - Be personal - Show your individual strengths - Don't be all over the place - Be on point - Avoid peak application time - Rejection is more likely if the manager has many application to scan ## Tips to get rejected here - Use AI with your introduction - I am a strong candidate because - Applying on side channels - LinkedIn messages and connect requests - Application send by mail - Devshop agencies calling my private phone number - Just where did you got my phone number from I have never published anywhere? - CV - .docx attachment - won't open - Bad layout - Have typos in your CV - Symphony - Kubernets - Bullshit language like this - delivering high-quality software solutions across various industries - rock star, ninja, wizard - I can do everything, too many acronyms, no focus - Core competence in other skills when not required - Frontend / design for backend developer - Ruby On Rails for a PHP Symfony developer position - SEO for a DevOps position - IPTV for any position here - Too much emphasis on dated tech - Twitter Bootstrap - jQuery - CodeIgniter - Angular - Ajax - XHTML - Very long answers, Russian novel style - No time to read - Missing required skills - When it says 5+ years experience, that is expected - When it says we are looking for a Symfony developer, that is expected - Company culture mismatch - corporate background - Hiring hacks - gaming the system ## Conclusions Hiring is hard. We are a small team. It's one of the things we also need to do, we are not very professional about it. Yet we like to do it on our own and mostly manually. It's fun connecting with interesting people. We have not even touched the interview part. # HTTP/2 reality check Source: https://blog.fortrabbit.com/http2-reality-check Created: 2016-05-09 Author: Frank Lämmer Tags: opinion > HTTP/2 promised faster delivery. What measurements on a real PHP hosting platform actually showed, and where the gains went. ## HTTP/2 expectations HTTP/1.x — the rock on which the internet is build — is [really old](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#History). The [HTTP/2 standard](https://http2.github.io/) in comparison is a true youngster with it's [RFC](https://tools.ietf.org/html/rfc7540) being published in May of 2015. Nonetheless it is already supported by many [servers](https://github.com/http2/http2-spec/wiki/Implementations) and [browsers](http://caniuse.com/#feat=http2). A short recap on what HTTP/2 brings to the table: - multiplexing: One TCP connection for multiple simultaneously requests - header compression: reduced overhead - binary: no text, just gibberish We have all seen the impressive (and similar looking) demos from [CDN77](http://www.http2demo.io/) and [Akamai](https://http2.akamai.com/demo). So let's see what can we add to that. ## How we tested The tests were developed around our internal discussions on the topic. They are just a quick sketch to investigate our assumptions. They were initially not meant for public - neither as a fancy demo, nor with a scientific approach. Still, we think they might be interesting so we decided to publish them anyway. All tests, unless specified otherwise, were run in various browsers: Chrome (50, 51, 52), Chromium (49), Safari (9.1.1) & Firefox (48). ## The Chuck Norris test ![Chuck Norris text](/images/chuck-norris-test.gif) Our first attempt was to rebuild the tests we have seen from others. Indeed, it worked well: You can obviously see how HTTP/2 delivers those 200+ images much faster - you don't even need a timer. That's sure looks like good marketing, but we're not if it answers any "real world questions". - **[See the Slightly enhanced Chuck Norris test](http://http-test-2.frb.io/chuck-norris.html)** ## The extended test series > Never trust a statistic you didn't forge yourself. Ok, we admit, it was not only to test HTTP/2 - what we actually set out to do was testing our new Object Storage and compare it against our older implementation and other solutions. Here is what we asked: - How does file size factor into the performance? - How does TTL due to location factor in? - How does delivery from local file system compares to Object Storage? - How does our Object Storage compares to S3? - How does our HTTP/2 implementation compares to other HTTP/2 services?
Test 12 & 13 side by side with Chrome Developer Tools.
HTTP/2 (left) starts immediately but has a longer (green) Time-To-First-Byte.
HTTP1 (right) loads the images one by one, see the steps.
45 images load equally fast in both protocols in this test.
- **[See all 20 extended tests](http://http-test-2.frb.io/)** When running/looking at the tests yourself, mind: ### Caches There are two caches involved here: On the server side we have nginx, which stores frequent requests in memory and/or on local disk before handing the requests further down the rabbit hole. Cache busting, aka attaching a random query string, allows to circumvent that. There are tests with cache busting and without. On the client side there is the web browser cache. In real-life scenarios this is a huge performance gain, but must be controlled in testing, of course. We used the Developer Tools to turn of local caching. What was interesting for us, that circumventing the nginx cache did not reduce performance that much. Depending on the browser, the performance degraded between 0% and 30%. This merits further investigation - as does the gap in performance between browsers (later Chrome versions performed worse). ### TLS overhead It would be interesting to see HTTP/2 over TLS and HTTP/2 over an unsecured connection. Unfortunately we cannot test that, as browsers only support HTTP/2 over TLS. So we tested: HTTP/2 (via TLS), HTTP/1.1 via TLS and HTTP/1.1 plain. Unsurprisingly HTTP/1.1 via TLS came out worst. Surprisingly HTTP/1.1 "felt" in many scenarios akin to HTTP/2. We assume this is because modern browsers already utilize multiple, concurrent connections to load page assets, which gives it a feel akin to TCP multiplexing. ### Location Not a big surprise: The distance between the browser and the web server plays a major role. We have tested both of our data center locations US (Virginia) and EU (Ireland) from Berlin. We hoped that HTTP/2's TCP multiplexing would have a bigger impact, but — again — the concurrent requests browsers already make resulted in about the same experience. In consequence: We already have ideas to extend our Object Storage by CDN functionality. ### Number of requests per page How many assets will the average web application load? The fortrabbit marketing website currently loads about 55+ additional assets per page. That is actually quite slim, compared to other sites. Spiegel online, a major German news page, generates about 260 additional requests. So what is a realistic number here? Today, we work around HTTP/1.1 limitations by: Inlining JS and CSS or even images; concating JS & CSS and even sharding assets across domains. Those techniques might become [anti-patterns](https://docs.google.com/presentation/d/1r7QXGYOLCh4fcUq0jDdDwKJWNqWK1o4xMtYpKZCJYjM/present?slide=id.p19) with HTTP/2, although they still would be more effective in some extreme edge case scenarios. We think, that the trend will go towards more assets, leading to more parallel requests. As expected, our tests revealed that HTTP/2's strength played out better with more concurrent requests: The earlier tests with 50 assets did not show much difference vs HTTP/1.1, but the tests with 200+ assets did. Again, we think that this might be because modern browsers already do concurrent requests with HTTP/1.1. ### Size and bandwidth Size and bandwidth must, of course, be considered. The above tests contain some scenarios with large amounts of data, which should saturate most consumer uplinks easily. Once the bandwidth is saturated, there is not much HTTP/2 can to to improve the performance, of course. Unsurprisingly, this is what our tests showed as well. ### Type of elements We — and most other HTTP/2 tests — have only covered to load a ton of images. A real life websites loads all kinds of stuff. Afaik, images are non-blocking: a web page will render without the images showing place holder icons and alt text. JS (unless loaded async) usually has to be downloaded in full. The same goes for CSS (can't even be asynced). How does it feel when those come over HTTP/2? We haven't tested that yet. ## Conclusions I think we can safely say that HTTP/2 is not any slower than than HTTP1. And we also know by now that you should never ever trust any marketing buzz (including this one). Apart from that we conclude that our New Apps are much faster than our Old Apps and that New Apps combined with the Object Storage are even faster. Never mind all this for your pet project. But maybe you are developing an image heavy eCommerce project? Then this might come in handy. ![Bush is doing it wrong](/images/bush_doing_it_wrong.jpg) Maybe we are just holding it wrong? You know better? Please call us, we are looking forward to hearing from you. ## WTF Did you know that Google uses a `quic/1+spdy/3` protocol - based on UDP? ## Further readings By the way, have you seen our [httpSpeedy](/httpspeedy) article from last year? Here we also reflect on "SSL everywhere" and "HTTP/2 trade-offs". In any case, check out [HTTP/2 Considerations](https://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/) by William Chan. # httpSpeedy? Source: https://blog.fortrabbit.com/httpspeedy Created: 2015-11-05 Author: Frank Lämmer Tags: opinion > TLS, SNI, certificate authorities and HTTP/2, and why a hosting platform should not rush any of them into production. > The future is here, it's just not evenly distributed yet. William Gibson TLDR: This article is about the acronyms TLS/SNI, HTTP/2 & CAs and why not to make hasty changes. We are running and building our PHP hosting platform here. The fun part for my job is to evaluate new technologies. So I recently did some research into the next version of the Hyper Text Transfer Protocol. Here are my learnings. Disclaimer: I am not a hardcore techie. ## 1. Hello TLS & SNI To establish a HTTPS connection (on a custom domain) we currently offer SSL termination, which is implemented as a dedicated load balancer. The product is a bit pricey, since we buy it pricey. It is also all too complicated for my personal flavor. But soon, we are going to release a SNI based TLS variant. It basically does same, but we can install multiple certs on a single load balancer which enables us to offer the service for a more affordable price. So far so good, now how can we improve further? ## 2. Hello HTTPS/2 The Apache web server project recently announced support for HTTP/2. So I needed to have another look. Without wanting to go into all the techie details: overall HTTP/2 sounds promising. Faster page delivery (just think of multiplexing) without any code changes — as it is fully backwards compatible. And it already has a huge browser support. So what is holding us back? ## 3. Hello "Let's Encrypt" One thing that bothers me is the shady [Certificate Authority](HTTPS://en.wikipedia.org/wiki/Certificate_authority) business. You know these 90ies-style websites were you pay to get a double-opt-in email and some text-blob-strings (the actual certs). The [Let's Encrypt](HTTPS://letsencrypt.org/) initiative may soon make this obsolete and may bring mass adaption of secure website connections — HTTPS; a commodity. ## My obvious conclusion All browsers are supporting HTTP/2 only over a secured connection. Now the idea simply was to combine those three technologies above to a seamless experience on our platform: HTTP/2 everywhere, custom domains must be routed over HTTPS which is fairly simple to set up and doesn't even cost extra. Everything is more snappy, more secure. We have something to play for the early adapters and even better Google rankings for our clients (as rumored). ## Hello tech trade-offs I learned that HAproxy (our load balancer of choice) is expected to support HTTP/2 fully with the next release version 1.7 which is expected not sooner than September 2016. We shortly discussed switching to NGINX for that reason. While continuing my research I stumbled over the excellent article by Will Chan: **[HTTP/2 considerations and tradeoffs](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/)**, which marked a turning point in my thinking. Read it, if you have couple of hours. I learned about the major technical considerations when implementing HTTP/2: [Network performance](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/#NetworkPerformance), [Scalability & DoS](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/#ScalabilityDoS), [Complexity](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/#ImplementationComplexity), [Binary protocol](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/#TextBinary), [Deployability](HTTPS://insouciant.org/tech/http-slash-2-considerations-and-tradeoffs/#Deployability). These reasons alone scared me enough not to start a field test with this new technology in production. But the most interesting part — for me at least — was the non-techie part: ## Hello political considerations The article also gave me insights into the process of agreeing on specifications. I learned how much such a technical topic is driven by the "special" interests and opinions of the involved parties. I used to think that HTTPS — end-to-end encryption — everywhere is a good idea, as it is a general privacy improvement. I am not so sure about this any more: > "SSL everywhere" is security snakeoil: The CA system is broken, trojaned, corrupt and unsalvageable. [Poul-Henning Kamp](HTTPS://twitter.com/bsdphk/status/659485236473044992) - FreeBSD, Varnish … I don't believe in conspiracy theories all that much. But in post-Snowden times (and today on Guy Fawkes night), we probably should think twice when it comes to security and privacy. Many [comments](HTTPS://www.schneier.com/blog/archives/2014/11/a_new_free_ca.html#comments) on the article by Bruce Schneier about Let's Encrypt suggest not to trust this free service, just because of the involved companies. Alternative free CA solutions might be: * [CAcert](http://www.cacert.org/): community certificates (not trusted by browsers by default?) * [StartSSL](https://www.startssl.com/): commercial CA provider with a free version (looks oldschool) ## My learnings On a personal level I was reminded to question the things around us. I personally would prefer anonymity not only privacy when surfing most of the web. On a professional level the same applies. We need to make careful decisions in the interest of our clients. Just the same with PHP7: we will wait until it is ready for production. ## Furher readings * [Is TLS fast yet?](https://istlsfastyet.com/) * [The US government https only standard](https://https.cio.gov/) * [HTTPS everywhere](https://www.eff.org/HTTPS-EVERYWHERE): browser extension to brut-force https connections * [HTTP/2.0 — The IETF is Phoning It In](https://queue.acm.org/detail.cfm?id=2716278): ACMqueue article (2015) * [Security Collapse in the HTTPS Market](https://queue.acm.org/detail.cfm?id=2673311): ACMqueue article (2014) * [Making the Web Faster with HTTP 2.0](http://queue.acm.org/detail.cfm?id=2555617): ACMqueue article (2013) * [HTTP Performance Is a Solved Problem](http://www.infoq.com/presentations/HTTP-Performance): Talk by Poul-Henning Kamp # I love assets Source: https://blog.fortrabbit.com/i-love-assets Created: 2015-05-18 Author: Frank Lämmer Tags: webdev > Automated asset pipelines for CSS, JS and images: how to build them and how to deploy the output when storage is no longer persistent. ## The why, what and how of automated static asset pipelines We are currently working on a [big platform update](/roadmap-to-hack-app). For this, we plan to drop one of our core features: the locally attached network storage. That means that future Apps will not have persistent storage any more, we call them "ephemeral Apps". This new architecture will be faster and even more stable. That also means that those 12-factor flavored Apps will not have the convenient SSH/SFTP access any more and you'll only deploy using Git. But not all parts of your App are supposed to be part of Git: Runtime data like log files and user uploads and also **compiled static assets** such CSS/JS & images live outside Git. Further on i would like to explore opportunities to generate and deploy those fixed static files. Let's have a look back first: ## A look back: Legacy CSS/JS workflows I think I first saw compressed JavaScript with jQuery. I learned about YUI compressor, but back then it looked like big guys tech to me. The JS and CSS I was writing where exactly the files that got delivered to the client. Remember [web standards](http://www.webstandards.org/), XHTML 1.0 Strict? Things where clean and easy. That changed when I began working with CSS preprocessors. I suddenly needed a workflow to separate the authoring files from the one used in production. So i found the tooling to automate those build-processes and even help to do more. Things became "ugly". ## Why to pipeline The benefits of using automated build processes are obvious: 1. make your life easier with better authoring tools 2. speed up page delivery with optimized files ## What to pipeline Everything is possible. The most common tasks are: **Compiling CSS preprocessors**: You enjoy authoring your CSS in less, Sass or Stylus. So you also need to convert this to plain CSS for production at some point. **Compiling to JS**: You are writing your JavaScript in a language that compiles to JS, like CoffeeScript, TypeScript or Dart. So you'll also need to compile this to plain JS for production. **Concating**: You multiple single JS or CSS files in authoring, but you don't want to have that many different calls for external files in production, so in the building pipeline you join them together to one big file. **Image optimizing**: You can make your vector- and raster-images even small than your graphic editors "save for web" export — use gifsicle, jpegtran, optipng, svgmin and pngquant. **Minifying**: Get rid of all the characters that are only necessary to keep your files readable for humans. Remove all those white-spaces, and line-breaks, redundant declarations: compress it, uglify it. **Gzipping**: Now turn your one line of uglified code into mojibake to make even smaller. (**Deploying**: Get all the stuff up.) ## How to pipeline That's what you want to have done, but which technology stack to use? ### Local JS task runner TLDR; That's the popular choice these days, just use Gulp. Why not use front-end technologies when dealing with front-end files? Task runners like [Gulp](http://gulpjs.com/) and [Grunt](http://gruntjs.com/) are a popular choice to automate your development tasks. They are based on Node.js, but they work side by side with whatever kind of language you are coding in. ### Your framework Some frameworks have built-in asset solutions. These probably better fit into your workflow and come with additional features like: File versioning (for cache-invalidation), Dev/Stage scenarios, link-rewriting, deployment helpers … #### Ruby on Rails Let's remember: [SASS](http://sass-lang.com) was one of the first CSS-preprocessors. It's written in Ruby. In addition [Compass](http://compass-style.org/) is probably the first generation of micro-mixin-framework. Rails itself handles CSS/JS automation with [The Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html). #### Symfony Symfony has a new (2015-04) [Asset component](http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component) as well as workflows to integrate [Assetic](https://github.com/kriswallsmith/assetic) with Symfony and Twig. There is movement! @WouterJ just recently added an article to the Symfony Docs on how to [use Bower alongside with Symfony](https://github.com/symfony/symfony-docs/pull/5159), followed by a proposal for a new article on a [pure PHP asset solution](https://github.com/symfony/symfony-docs/pull/5166). #### Laravel Laravel has a clever approach by just integrating predefined Gulp tasks. It even has a fancy name: [Elixr](http://laravel.com/docs/5.0/elixir). #### Other frameworks You get the point. Mature frameworks have this built in. Play has [the Assets controller](https://www.playframework.com/documentation/2.0/Assets), Django [deals with it](https://docs.djangoproject.com/en/1.8/howto/static-files/). ### GUIs DesignerDevelopers (like me) might consider stand-alone Apps with "click interfaces". I found [CodeKit](https://incident57.com/codekit/) useful to get started, other alternatives are [Koala](http://koala-app.com/) (free, cross-OS), [Crunch](http://crunchapp.net/) and [PrePos](https://prepros.io/). ## How to deploy Now you have automated workflows to generate optimized versions each time you save your original JS/SASS file. How do you deal with it? Do you just put it in Git and deploy with the rest along, or do you define yet another asset pipeline task to deploy it. ### Static assets VS Git Source control was designed to deal with code changes in your original authoring source files. It's actually not the place to put your ugly files in. If you just put your assets in Git you'll have to deal with bad side effects like: 1. **No diffing**: Compiled static assets are binary, they consist of one line, impossible and not and even necessary to diff. 2. **Merge conflicts**: You'll run into conflicts when everyone in your team has "different" versions of compiled files. 3. **Bloating**: Your `.git` directory get's bigger and that makes everything slowers. **Shame on us!** We are supporting you in such bad practices with "Git push to deploy". It's what everybody loves as it is such a convenient way to upload code changes. The only problem: it's a hack. Now what can we do about it? #### 1. Put assets in Git, work around quirks You can at least make yourself more comfortable by dealing with some of the quirks. Andrew Ray [describes in his blog](http://blog.andrewray.me/dealing-with-compiled-files-in-git/) how to: - Exclude built files from diffing in `.gitattributes`, - don't let compiled files conflict in a rebase with a merge driver in `.git/config`, - rebuild files automatically with a Git hook. Other solutions to use branches or submodules for this. #### 2. Put assets in Git Large File Storage That's just an idea that came up while researching this topic. After [git-fat](https://github.com/jedbrown/git-fat) and [git-annex](http://git-annex.branchable.com/) [git-lfs](https://git-lfs.github.com/) is a new approach to actually deal with large binary files, but hey why not use it for something like this. Git Large File Storage needs to be installed on both, the client and the remote server to work. #### 3. Exclude from Git, generate static assets on remote In general we assume that you are compiling your assets in your local development environment. One can also consider to have the same setup on remote so, that you everything can be compiled on remote after a (Git) deployment (or even live on each user request) again. I don't think that this makes much sense, as it is probably hard to debug errors for instance when your local dependencies differ from the remote ones. #### 4. Exclude from Git, deploy separately Exclude your static assets from Git at all. Deploy them in a different way, maybe even to a different space such as a cloud object storage space. That means you have two deployments (with a platform like ours) — Git push and the "other one". The "other one" might be some rsync or some upload to an [external object storage provider](http://help.fortrabbit.com/external-services#toc-cloud-storage). The "other one" might be triggered with Git Hook. That is probably the most professional and most complicated way. We do so with our web properties here — all JS, CSS and images are served from S3. This way you can also easily hook up a CDN for those assets. Serving those files from another domain improves performance (non-blocking). Now, with our upcoming 12-factorish App you can't SSH in any more, so you'll probably need some kind of external space. A separate cloud storage might also help you with your runtime data. > That's dogma over practicality. **[John Albin Wilkins](https://www.drupal.org/node/1821780#comment-6661544)** in a Drupal Community comment ## Conclusion Yes, asset pipelining with task runners makes sense. The automation of mundane tasks not only helped us to increase productivity; the file optimizations reduced page load time significantly. Now it only seems to us, that there are a thousand ways to do it. We are designing our service around deployment and hosting. So it's crucial that we get this right. What's your opinion and what's your practice? We are curious if you are considering solution 4 where you separate assets from Git deployment. Are you using this in practice, which cloud storage provider are you using? If using AWS S3, do you make use of IAM? We are considering to implement a new "cloud storage" (working title) component, which basically makes using AWS S3 much more convenient, integrated tightly into fortrabbit. The upcoming [Amazon Elastic File System](http://aws.amazon.com/efs/) also looks promising. It could be a replacement for the persistent solution we currently have, although we are skeptical as we there are always two sides, NFS and Operating System. But for sure we'll keep an eye on that. # Image processing services intro Source: https://blog.fortrabbit.com/image-optimization-services-overview Created: 2021-04-14 Author: Frank Lämmer Tags: opinion > A field guide to image processing and optimization services: what problem they solve, which providers exist, and the alternatives. ## Scope and disclaimer This is a quick overview about image processing services. This is not a deep comparison or a step by step integration guide. The author has only little or no first hand experience with the services themselves. There is no business association. ## What is image hosting as a service? An image processing service is a convenient collection of tools to easily deliver images for your website. It usually consists of a Content Delivery Network (edge caching) and an image transformation engine (image resizing on the fly). It fits nicely in a micro service oriented architecture. There is often also an easy to use API accessible by passing URL parameters. Consider requesting a thumbnail version of an image like this: `image.jpg?height=400&width=400&mode=crop`. ## What problem does image hosting solve? ### Faster websites Images are often the biggest byte chunks of websites. That's why you want your images to be as small as possible and to be delivered in sizes relevant to specific visitors. Also you want the images to be served from a location that is close to the visitor. ### Better hosting resource usage Your hosting service has limits. Here at fortrabbit, our Apps are designed for fast web delivery processes. When you upload photos to a CMS, these images need to be processed to multiple formats: + A thumbnail and a large version + Multiple sizes for devices with different resolutions + Multiple image formats for different browser engines, webp and jpg So one uploaded original image might result in 20 images files for web delivery. Here is a simple example HTML markup for a full-sized image that can be served in 4 different sizes and two formats (webp and jpg): ```html Cute cat pic ``` With standard web servers image crunching is usually done by open source tools like [ImageMagick](https://imagemagick.org/) or [GD](https://github.com/libgd/libgd). Image transformation is a CPU heavy task that can take some time (even seconds!) until executed and it can also use a lot of memory. Calling image libraries is wrapped in PHP on webhosting services like ours. That means a PHP process is occupied until an image has finished being converted. Good news is, once an image version is created, it can be stored on disk for later usage. With suboptimal configuration (crazy eager loading, too many sizes) and/or wrong settings (no cache on disk) and/or extensive use (super large source images or many images) this can lead to serious web delivery problems or even end in 504 time-out errors. In addition to standard image processing, additional tools (jpegoptim, optipng, pngquant, SVGO, gifsicle) to further optimize images are popular among performance-aware frontend developers these days. These tools often require a lot of processing power and are therefore not available here. ### How an image hosting provider works Most image hosting services work as "origin pull CDNs" at their core. That means images are uploaded as usual with your CMS like so: + `yourdomain.com/uploads/newimage.jpg` Then you configure the image hosting service to use that folder. In your templates instead of using a relative path on the domain of the website use an external link like this: + `user.imageprovider.com/uploads/newimage.jpg` In addition you can set up a sub-domain so you don't have to use the domain of the image provider: + `cdn.yourdomain.com/uploads/newimage.jpg` After that you can use URL parameters to grab a different versions: + `cdn.yourdomain.com/uploads/newimage.jpg?height=400` + `cdn.yourdomain.com/uploads/newimage.webp?height=400` Additional flavours and features are available. ## Image hosting providers overview Here is a list of some image optimization services: + [imgix.com](https://www.imgix.com) + [imagekit.io](https://imagekit.io) + [piio.co](https://piio.co) + [libpixel.com](https://www.libpixel.com) + [imageboss.me](https://imageboss.me) + [kraken.io](https://kraken.io) + [sirv.com](https://sirv.com) + [cloudinary.com](/cloudinary.com) There are client libraries for programming languages. There are also plugins for popular CMS's like WordPress, Craft CMS or Shopify and Magento to easily include the services. Some providers can also integrate with an AWS S3 bucket. Most will have HTTP/2 or even HTTP/3 support. Some might have AI/ML tools for intelligent cropping or automated tagging. Some also offer video encoding. Comparing prices is a bit hard, since vendors use individual pricing models - most are usage based (pay as you grow). ## Alternatives ### CDN While there are dedicated image processing services, the service offering can also blend with other services. Some CDN providers also provide image transformations services: + [developers.cloudflare.com/images](https://developers.cloudflare.com/images/) + [cloudinary.com](https://cloudinary.com/) + [bunny.net](https://bunny.net/) That might be convenient since it gives you a one stop shop. ### Transform images on the web server For normal usage you can still use your general purpose web server to do the job. ### Run your own You can also host your own worldwide image transformation service. [Imaginary](https://github.com/h2non/imaginary) is open source software written in Go. ### Others You can also tinker together something like this on your cloud infrastructure provider using serverless functions. On AWS there is some [Serverless Image Handler](https://aws.amazon.com/solutions/implementations/serverless-image-handler/) glue. ## My experience Are image transformations services worth the money and the effort? It depends! You should definitely look into this if you are running a successful e-commerce site. Sometimes using such a service can be an economic choice: pay some more for the image service while paying less for the web hosting itself. I do a lot of client support for our hosting platform. I often get requests for advanced image optimization because people see a bad Lighthouse score or they have read some article like [Creating optimized images in Craft CMS](https://nystudio107.com/blog/creating-optimized-images-in-craft-cms). That's one of the reasons I wrote this blog post. I would recommend first trying to take full advantage of the tools available before thinking about further optimization. Often the jpg compression level can be set to lower level when images are scaled down. Sometimes I see that images are not served in optimal sizes and resolutions. Sometimes I see other performance issues that might be fixed first. My tip: Prioritize the areas of your website performance optimization. Go for the low hanging fruit first. Image sizes can play a major role. But before considering outsourcing image transformation, see what you can do with existing tooling and some creativity. # ImageMagick issues Source: https://blog.fortrabbit.com/imagemagick-issues Created: 2019-03-04 Author: Frank Lämmer Tags: chronicles > The backstory of a week of ImageMagick trouble on the platform: what broke in image transformations, and what was done about it. ## ImageMagick on fortrabbit As you know: [ImageMagick](https://www.imagemagick.org/) is a very well known image transformation library which has been around for ages. It lives as a ready-to-run binary in many operating systems. It helps you to transform images, like from one size to another (big > thumb) or from one format to another (PNG > JPG). For PHP there is an additionally interface, called "imagick" which is installed as an extension and exposes a programmable interface for ImageMagick in PHP. The combination of these two in PHP is so popular, you could call it a standard of the LAMP stack. You will most likely have been using ImageMagick for years. Whenever PHP does an image transformation, like when thumbnails are created, it is probably doing all the magic in the background with ImageMagick. The GD Graphics Library is an alternative also available here. ### A design trade-off Our Apps are designed as lightweight containers serving fast PHP processes. Allocated resources are limited. Image transformation on the other hand are resource hungry by nature. Loading images in memory (uncompressed) requires a lot of RAM and processing and compressing them with ever advancing codecs will keep even the most modern CPU busy. You can try it at home: Transform images with any program and watch your CPU spike. From our point of view, in an ideal web application architecture, such operations should not be mixed with anything that happens on the frontend. Image transforms should not make any user wait. With the Professional Apps we offer [Workers](https://help.fortrabbit.com/workers) to outsource such resource hungry tasks into the background. But setting this up requires extra efforts, which might be overkill for a standard website. So we aim to bring a good solution for Universal Apps - a balance between performance and expected results. We therefore have been limiting ImageMagick memory usage with a "policy.xml" file for quite a while already. The limits are designed to give each ImageMagick process a reasonable limit while still performing as expected. With Universal Apps, each ImageMagick process was limited to 64 MB of memory. This setup has worked great for years. ### Recent imagemagick updates We recently updated ImageMagick from version 6 to version 7. One of the goals was to bring "**webp**" support 😎. It now seems to us, that something changed with the new ImageMagick version. ### Hard to detect issues We rolled out the update around a month ago (10th of Feb) and we initially did not see any issues, neither in our tests we did before nor in production after the update. But one by one, more and more image transformation related issues appeared. So we tried to find a connection between them. ![](/images/imagemagick-corrupted-image-1.jpg) ![](/images/imagemagick-corrupted-image-2.jpg) Sometimes, but not always, great abstract art like the examples above was produced. Source: footage from clients. We finally found out, that image transformations done on larger images coming in (>3000px each side) and relatively large images going out (>600px each side) tend to lead to errors. Those error cases either have been generating the grey images or we simply saw hanging processes and 5xxx errors with no images at all in the end. Only a small number of clients were affected by these issues, but for some of them issues were critical. ## The current situation We have investigated all kinds of settings. We now think to have found a solution. It offers much better use case coverage in the ImageMagick policies. A [patch](https://status.fortrabbit.com/incidents/ysbw39h49n1s) has been applied globally just recently. Now, Apps are getting the maximum available memory for ImageMagick. If your Apps runs on a bigger plan, it gets more memory for ImageMagick. The default also increases from 64 MB to 128 MB. We also increased the swap size that ImageMagick itself can use. Those two settings together (RAM & swap) have provided much better results in our testing. We are carefully watching results now. The patch is not perfect, we still see few cases, with very large images that will still fail. More memory (bigger plan) or smaller source images can also help. We are still investigating this and are looking for ways to further improve the service further.

Further actions

To get rid of past failed transformations, your action might be required. Image transformation are usually cached on disk. Those caches now - after the incident was going on for almost a week - can contain corrupt files. Image transformations are often only generated the first time a user calls a page containing images. Generated images are then cached on the local file system and will be available without any computing from there on. Now, there might be corrupted files on disk with your App already. So if you still have issues with image transformations, please make sure to clear the caches first, so that the images can be re-generated. How to delete image caches depends on the framework or CMS in use, maybe settings and even plugins. The actual cache files are kinda temporary runtime data, so they are usually not stored with Git. In most cases, the caching is a combination of files on disk and entries in the database. The CMS / framework needs to keep track of cached files. So there likely gonna be methods available. Simply deleting files might not solve the issue. Pro Apps don't have persistent storage. So the transformed images, when configured correctly will end up on the Object Storage. There might be local copies on the ephemeral file system as well. The local copies will be deleted with each deploy. Again, usually you just have to use the available methods. With Universal Apps, the generated images usually will end up on the file system of the App. ### Craft CMS Craft CMS users have three ways to trigger a rebuild to delete already cached broken images: 1. **Control Panel**: You can do so in the Craft Panel (on fortrabbit) under "Utilities" > "Clear Caches" > Check "Asset transform index". Make sure that the flag "allowAdminChanges" in "general.php" for the fortrabbit environment is set to "true" (default is false here), otherwise those options are not accessible. 2. **Craft CLI (3.0.37+)**: Login via SSH and issue `php craft clear-caches/transform-indexes` 3. **MYSQL**: Delete specific rows in "assettransformindex" or truncate the whole table. ### Laravel Laravel does not have image transformation capabilities on it's own by design. Libraries are often used. The most popular one is [Laravel Medialibrary](https://docs.spatie.be/laravel-medialibrary/v7/introduction). Please see the docs of what you have in use. ### WordPress WordPress of it's own does not seem to bring any methods to deal with image caches. There is a dedicated plugin called "[Regenerate Thumbnails](https://wordpress.org/plugins/regenerate-thumbnails/)". But all popular cache plugins, like "W3 Total Cache" and "WP Super Cache", have options to clear image caches builtin. --- Sorry for the inconvenience this have caused on your side, one more time! Contact us if you still have trouble, we aim to help. # imageMagick patch 2 Source: https://blog.fortrabbit.com/imagemagick-update-2019-08 Created: 2019-08-16 Author: Frank Lämmer Tags: changelog > A second ImageMagick patch rolls out across the platform, with the rundown of timing and the downtime to expect for Uni and Pro apps. ## Run down and timing The updates will affect all Apps (Uni and Pro). There is no - or just a very short (>1 minute) - expected downtime for web delivery. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we do not expect service interruption. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. TIP: You can also subscribe there. We are going to run those updates **Tuesday, 20th of August 2019** first in US and a few hours later in EU. The total expected maintenance window is 4 hours for each region. - **US maintenance** — 08:00 UTC + 4 hours window - **EU maintenance** — 13:00 UTC + 4 hours window ## Addressing imageMagick performance We have once again optimized our imageMagick (the open source library squeezing your jpgs) distribution for more speedy image transformations. We are looking forward that this will make transformations faster, especially for image-heavy websites. ### Backstory Back in February we ran a major upgrade on imageMagick - from version 6 to version 7 — most prominently now featuring `webp` support. But, some serious performance degradations followed. They have been addressed with a quick follow up patch — see our [blog on initial imageMagick issues](/imagemagick-issues). Back then we adjusted the `policy.xml` to better make use of available memory. The situation got much better, but some Apps where still suffering. ![](/images/imagemagick-corrupted-image-2.jpg) Broken images like the one pictured above and/or frozen websites — 504 time out errors — when image transformations where ongoing here and there. ### Learnings with our clients We have had hard times identifying common patterns on the issues. They were happening under different circumstances and setups. But we are very fortunate to have such great clients! **Thank you!** Detailed and excellent bug reports and even test pages where provided. We learned a lot together. ### Image size matters Digital photo cameras are getting better and better over time. So the source images are having higher resolution nowadays. Mobile phones have 16 MBP and professional cameras up to 45 MBP. With our testing we found that the input size always matters, as the full image needs to be read in memory, even to produce the tiniest thumbnail. But the target output size, also seems to matter. The worst transformation case is a lot of huge image that need to be transformed into big images. ### Craft CMS in focus While there have been some cases with WordPress, most often we dealt with Craft CMS installations. We learned that Craft 2 was more affected than Craft 3 and probably that an older PHP version (7.1) also has a negative impact. #### Craft CMS queueing The current implementation of the **Craft CMS web job queue** can break your website and can also play a negative role in this context. Oliver developed the [Craft Async Queue plugin](https://github.com/ostark/craft-async-queue) to address this. We recommend to use it in any way — with or without many images. It often helps to make better use of available resources. Andrew Welch just blogged about [robust queue job handling in Craft CMS](https://nystudio107.com/blog/robust-queue-job-handling-in-craft-cms) — have a look. In our optimal hosting design thinking, the actual image transformations should not be done form the frontend PHP processes anyways. They should be outsourced to something like a Worker. Another alternative might be to outsource image transformations and delivery to an image hosting service such as IMGIX, Cloudinary and alike. ### GD as an alternative As a mitigation we often suggested to use "GD library" instead imageMagick. Most modern CMS and frameworks are supporting both anyways. It can easily be switched with a few clicks in our Dashboard. When only transforming JPGs the output quality might not be as good, but usually with less memory consumption and possibly smaller JPGs — it is still a considerable good alternative. It should be noted, that it will also choke, when the images provided are too big, but usually with a meaningful error about exceeded memory instead of just eating up all memory and blocking all processes. ## Blackfire fix for Craft CMS While trying to debug those performance bottlenecks in [Blackfire](https://blackfire.io) we found another issues: Blackfire does not report well in combination with Craft CMS and Twig. Template names did not showed up correctly. Something like `__TwigTemplate_5b91f909…::doDisplay()` was shown. We reported that as a bug and it was patched with the Blackfire extension version 1.27 which (hopefully) will also be included with the coming updates, so that we — and everyone using Blackfire in combination with Craft CMS — will finally get something more readable like this: `_partials/footer-nav.twig::doDisplay()`. ## The new imageMagick patch Last not least — we are now deploying a newly compiled version of imageMagick, optimized for faster transformations, with the following changes: - **HDRI is disabled.** We believe that High Dynamic-Range Images are not needed in this context of delivering general images swiftly. - **Q8 only.** Support for 16bit depth images is disabled. We believe all standard web image formats today are usually using 8bit anyways. The test results are pleasing: better performance through using much less memory — up to 75% reduction in RAM usage — while keeping the same quality. We will carefully monitor the roll out in production now. ### Cleaning broken images Your framework/CMS does not know if an image shows a cat or just grey lines. Broken jpg files need to be removed and the image transformations need to be re-run. Here is a brut-force way to remove all image transforms for Craft CMS (for Universal Apps) on the local file system: ```bash # 1. Login via ssh to the App # 2. remove transformed images from file like so: $ rm web/assets/*/_*/*.* # 3. clear caches $ php craft clear-caches/transform-indexes ``` Next time someones visits the website, all image transforms will be re-run (first unlucky user). The first run will take some seconds — depending on the number of images and size per page, but it will be faster than before and less error-prone. From the second visit on the images are cached on the server side anyways. ## Other client facing changes Alongside with under the hood updates, some new client facing minor patch versions will be installed as well. Here is the (hopefully) complete list: ### Changed PHP versions - PHP73 (7.3.5) > 7.3.8 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) - PHP72 (7.2.14) > 7.2.21 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_2) - PHP71 (7.1.29) > 7.1.31 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_1) < Support until end of year only! ### Updated extensions - mongodb (1.5.3) > 1.5.5 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - phalcon (3.4.3) > 3.4.4 - [release notes](https://github.com/phalcon/cphalcon/releases/tag/v3.4.4) - blackfire php probe (1.25.0) > 1.27.0 (see above) - blackfire agent (1.26.0) > 1.27.3 - [changelog](https://packages.blackfire.io/binaries/blackfire-agent/1.27.3/CHANGELOG) - `convert` **ImageMagick** (7.0.8-46) > 7.0.8-60 - [changelog](https://imagemagick.org/script/changelog.php) - `mysql` (5.7.26) > 5.7.27 # Improving DX for executing scripts Source: https://blog.fortrabbit.com/improving-dx-for-executing-scripts Created: 2025-04-02 12:28:52 Author: Vlastimil Holer > Making scripts with a shebang line run as expected on a hosting platform, by modifying the C standard library without giving up security. As you might know from our previous posts, we are working hard on a [new platform](https://new.fortrabbit.com) which will provide more flexibility and advanced features. One thing we focus on is also to make easy the running of scripts for end-users. Even when your current scripts had executable file mode, they couldn't be executed directly (e.g., `./myscript.php`), due to our restrictive settings they had to be always prefixed by the interpreter (e.g., `php myscript.php`). This is a bit annoying, sometimes it's a real complication. ## Current platform Let's first look at how is this restriction implemented on our current platform. Data for users' applications are stored on storage volumes, which are mounted on the machines with a flag that forbids running executables (see `noexec` option in [manual page for `mount`](https://manpages.debian.org/unstable/mount/mount.8.en.html#FILESYSTEM-INDEPENDENT_MOUNT_OPTIONS) command) even if there are files that normally could be executed. The flag instructs the Linux kernel to refuse (direct) execution of any executable, no matter if it's a binary or a script. This reduces potential attack surface from the malicious users and allows us to control what can be executed on the platform, i.e. only components preinstalled by us in global directories (`/bin`, `/usr/bin`, …). Users' scripts can still be executed, but they have to be ran with interpreter commands always explicitly specified on the command line. While it's a way most users can deal with, it's not straightforward and it's a complication compared to a local development environment or unrestricted VPS. See what I mean on the example: ```bash # Login into your application in current platform ("example" used as a placeholder) $ ssh example@deploy.eu2.frbit.com ––––––––––––––––––––––– ∙ƒ ––––––––––––––––––––––– # Create a script named myscript.sh, give it executable file mode example:~$ echo -e '#!/usr/bin/php\nmyscript.php example:~$ chmod +x myscript.php # Direct execution of script fails! example:~$ ./myscript.php -bash: ./myscript.php: Permission denied # Succeeds when executed via explicitly specified interpreter example:~$ php myscript.php Magic happens! ``` To summarize, on our current platform, you can't bring and execute your own binaries (due to storage volumes mounted with `noexec` option). You also can't directly run scripts, you always have to explicitly run them via an interpreter set on the command line. ## New platform For the new platform, the security concerns are still valid. We won't allow users to run their own binaries. But since nearly all users' executables are just scripts (shell, PHP, or Node.js), it's annoying to always run them prefixed by the interpreter. Moreover, it's not always possible to easily prefix commands if they are hard-coded in 3rd-party libraries. We wanted to improve on that. ### Scripts execution workflow First, let's review in a simplified manner how the actual script is executed on this example file `myscript.php`: ```bash #!/usr/bin/php Magic happens! ``` ### Problems The outlined solution is quite easy and effective for the majority of use cases, but it's not bullet proof. Firstly, it relies on having the `LD_PRELOAD` environment variable set properly. We'll initially configure the environment variable for our users, but it can be cleared and the solution might become ineffective. Therefore we have prepared a wrapper above the usual commands, which always enforces the override library no matter what the user has set. A small benefit is that the feature can be selectively disabled. Secondly, the solution works only for dynamically linked executables. This is the case of most common components preinstalled in our environment, including PHP and Node.js. It doesn't work for binaries, which are statically linked, don't use and don't depend on any local libraries (they are self-contained). Such binaries are nowadays (by default) generated by Go or Rust. We don't have anything like that preinstalled in our environments, so they are not an immediate concern, but in the Node.js world, they are quite common. Fortunately, our testing with popular projects from the Node.js ecosystem hasn't uncovered a serious issue so far that would prevent us from going this way. ## Summary We want the environments running users' applications to be as restricted as possible, but we understand there must be **balance between security and usability**. - We still forbid running custom executable binaries, but we came with a transparent approach, how users can directly run own executable scripts. - We have modified the C standard library functions responsible for executing files to early detect the script and evaluate the shebang directive. This normally happens in the kernel of the operating system, which is too late for us. - The solution is effective for all common system components (bash, PHP, Node.js, …). - The solution will not work for statically linked binaries, which don't use the shared C standard library. Testing so far hasn't uncovered any problem, but we expect we might need to deal with that from time to time in connection with the Node.js ecosystem. ## Addendum This is an example of the hidden engineering that goes into building our [new platform](https://new.fortrabbit.com). Many features are client facing, but the vast majority is not. Many features are not making it into production. # Looking for the perfect infra provider Source: https://blog.fortrabbit.com/infra-research-2024 Created: 2024-12-04 07:26:27 Author: Frank Lämmer Tags: chronicles > After a decade on AWS, a new platform is a chance to reconsider. How infrastructure providers were evaluated, and against which criteria. ## Our business In case you are new here, some background on us: We provide Platform as a Service (PaaS) for PHP based websites and applications. That means, fortrabbit is an abstraction layer on top of IaaS. That means, we buy larger amounts of computing resources from an infrastructure provider, then we slice, spice (our software solution) and sell it. That means, our clients can create serverful apps with `git push` deployment, instead of having to deal Linux and all that stuff. fortrabbit is a small bootstrapped business around for more than a decade. ## Why change We are building a [new platform](https://new.fortrabbit.com). That enables and forces us to question everything. We will be using Kubernetes, which translates to less lock-in and more independency. We are looking at Infrastructure as a Service vendors, if you are not as old as I am, you may be more familiar with the new term hyperscaler. ## Our criteria Here are our premises: ### Costs Hosting in general is considered to be a business of thin profit margins. Speaking to our clients, I don't get the feeling that they actually care much about the fact that our platform runs on a premium service. Our target audience are web developers, agencies, freelancers and startups. We try to push the idea that there is actually a quality of service with hosting, but in general, people are looking for CPU cores in exchange of pennies. I don't want fortrabbit to be a 'over-prized vanity service'. I aim to get the costs down to be able to offer affordable pricing. AWS has a profit margin of ~30%, they say. We don't. The egress traffic costs with AWS (EC2 bandwidth to internet) are around $0.09 per GB. This is not what our clients pay elsewhere. ### Data center locations We currently operate two data centers, EU and US. We hope to expand locations with the new platform. So, the availability of world wide data center locations is important for us. For now, we don't want to deal with different providers for different regions. Sadly, that rules out smaller providers. ### Environmental impact Is it a green cloud? I see this is getting requested more and more. That aligns with my personal views. In 2012 I wrote a [small rant about the dirty cloud](https://blog.fortrabbit.com/the-cloud-economically-attractive-but-what-the-about-ecological-impact). I was a bit surprised to find that the marketing pages about AWS green hosting are compelling to me. They seem more realistic and reasonable than some vague promises by others. ### Cultural match As a bootstrapped company we aim to build a sustainable business we can identify with. We are a small business. Optimally we like to have someone to understand us. ## The short list So we set out to see if there is a better alternative to **AWS** for us. We ruled out the other big cloud providers **Azure** or **Google Cloud**, because they seemed similar and equally big tech from our perspective. We are locked in to AWS. We know about the terminology, the interface and in terms of reliability, we have nothing to complain. We looked into some VPS oriented providers: **DigitalOcean** is offering many different service levels, also an app platform which we think is too similar to what we do. We looked at **Vultr**, **Civo** and others. **Linode** has a good reputation, but we are a bit uncertain about their future direction under new ownership by Akamai. We shortly considered **OVH** as a European alternative. | Name | Tech | Price | Eco | Match | Loc | Comment | | ------------- | -------- | -------- | -------- | -------- | -------- | ------------------------------- | | AWS | \*\*\*\* | \* | \*\*\*\* | \*\* | \*\*\*\* | Expensive but reliable | | Hetzner Cloud | \*\* | \*\*\* | \*\* | \*\* | \*\* | Only Europe and US | | Hetzner Bare | \*\* | \*\*\*\* | \*\* | \*\* | \*\* | Only Europe | | Vultr | \* | \*\*\*\* | \* | \*\* | \*\* | Metal and virtual | | Equinix | \*\* | \*\* | \*\* | \*\* | \*\*\*\* | Too B2B? | | UpCloud | \*\*\* | \*\*\* | \*\*\* | \*\*\*\* | \*\*\*\* | Looks cool. Runs on Equinix | | Rackspace | \*\* | \*\* | \*\* | \*\* | \*\* | Where are they heading? | | DigitalOcean | \*\* | \*\* | \*\* | \*\*\* | \*\*\* | Maybe too much of a competitor? | | Linode | \*\* | \*\* | \* | \*\*\* | \*\*\*\* | Now Akamai, not so cool | | Civo | \*\* | \*\*\*\* | \* | \*\* | \*\*\* | Interesting, but … | | Azure | \*\*\* | \* | \*\*\* | \*\*\*\* | \*\*\*\* | Big tech | | Google Cloud | \*\*\* | \*\* | \*\*\*\* | \*\*\*\* | \*\*\*\* | Big tech | | OVH | \*\* | \*\*\*\* | \* | \* | \*\* | Bring a fire extinguisher | This table does not say much. For some of the points we can really not judge. Exclusion criteria not included. We also looked at some smaller local providers offerings. ## Exploring Hetzner **Hetzner** got into our focus more and more. They are around for a long time. They have a good reputation among developers, in regard of price, performance and security. There is a lot of praise on Hacker News and Reddit for Hetzner. It's important to us that the provider is trustful. They are large enough, but still small compared to big tech. Their cloud solution is offered in Europe and the United States, but not in Asia or Africa (hm). The data center in US does not run on green energy (hm). They are from Germany, as we are. So we share the same requirements for privacy protection. Their hosting control panel looks simple, which feels like some fresh air. Last not least, it should be mentioned that **Hetzner (Cloud) is around half the costs of AWS**. This crazy number alone should be motivation to jump through some hoops. ### Technical tests Beside all the soft facts, there are hard facts that need to match in the first case: technical requirements and quality of service. We compared AWS, Hetzner, OVH and Vultr. The later two at this stage for reference. We wanted to know if we can somehow make our platform work on Hetzner, even with extended efforts and custom code from our side. Actually we planned to publish a much more detailed analysis of our performance tests. But it's too much effort to them in shape. Here are some notes to get you an idea: - Random write performance is not what we hoped for, comparable to Linode - While on AWS EBS volumes running Ceph we get ~12 MiB/s random write performance which is the same performance as random writes directly to an EBS volume - Hetzner's private network has latency that is on average twice that of AWS private network. - Sometimes Hetzner pings goes all the way up to 30ms. - No LB floating IPs (ETA?) - max. LB performance 40k concurrent connections, enough? or need of multiple LBs? - firewall rules are not configurable on LB - Private network isolated, but not encrypted! [Hetzner docs](https://docs.hetzner.com/cloud/networks/faq/#is-traffic-inside-hetzner-cloud-networks-encrypted). - How is private traffic handled across EU locations? - Unpredictable CPU HTs performance (dedicated instances) - Cross-node private traffic routed always through gateway - Separate private network for storage? - Routing capacity? - Max 100 nodes in private network, [Lowendtalk](https://lowendtalk.com/discussion/187187/very-disappointing-limitation-in-hetzner-cloud-max-100-servers-per-private-network), [Hetzner docs](https://docs.hetzner.com/cloud/networks/overview/) - Possibly higher latencies (at least +30%) than on EC2 - Possibly private network unpredictability ### Talking with Hetzner During testing, we experienced a network issue. Hetzner technical support solved it quickly, but our question for an explanation was not answered to our full satisfaction. We tried to get in touch with Hetzner sales to discuss our requirements and the results of our tests. I hoped to set up a call, but I was told by someone with a strong Bavarian accent that we mail our questions. We did. We got reply quickly, but somehow it was not compelling. Hetzner was slower, which we kinda expected. But the whole experience left us with uncertainty. ## Talking with AWS At the same time our new AWS account manager (number 7?) introduced himself and offered help in any regard. So I asked whether they convince us to stay. This started a series of calls. We talked to various solutions architects. I have mostly positive feelings about the process, although nothing really changed. The folks we spoke to where all great. Standard procedures were followed. We talked about our AWS setup and ways to improve that. From our perspective, mostly to save on costs. From their perspective, to make sure everything is 'well-architected'. But our requirements are different to other SaaS. We can not ask our clients to fullfil our expectations on their software design. Our clients have expectations that we need fullfil. Along the process we have been able to optimize the instance types to get the infra costs down by some more percentages. We also ignored some 'best practices' and service offerings. This saves costs and keeps us less dependent. ## Talking to UpCloud a bit late I loosely follow hosting market trends. UpCloud was known to me for a while. But I have not considered them so far. They got in touch with me and I learned that they extended their offering actively naming hosting providers as a target audience. That's a great match. We met and I am under the impression that they really want to get us a client. That alone feels great. In other aspects, it also looks like a very good match: The price is better than with AWS. We have a personal connection. Data center locations are not a problem and most of them run on green energy. ## State today Developing our new platform already takes much longer than expected. This infrastructure provider research, of course an important necessity, was one of many deep rabbit holes. It had to end. Unfortunately, we haven't got any more time to properly evaluate UpCloud on a technical level. So, we will for now stick with AWS to ship something. Maybe we are trying to square a circle? All we want from our future hosting partner: data centers in all parts of the world, green energy, reliable and fast technology, an affordable price, a partner we can meet on eye level. I plan to come back to this. # Integrating codeship with fortrabbit Source: https://blog.fortrabbit.com/integrating-codeship-with-fortrabbit Created: 2013-08-28 Author: Ulrich Kautz Tags: webdev > Set up continuous integration with Codeship and deploy the result to fortrabbit, for teams that want tests to gate a release. ## fortrabbit + Codeship We have got a lot of requests concerning **continuous integration** lately. That's why we've published a new general [article](http://fortrabbit.com/docs/in-depth/integrating-external-ci) in our docs on how to integrate CI in your fortrabbit workflow. Pieter from [wercker](http://wercker.com/) also just published this [great article](http://born2code.net/blog/2013/08/26/Deploying-from-wercker-to-fortrabbit/) on how to integrate fortrabbit with wercker. Here is another one from us on how you could something similar combining [Codeship](http://codeship.io) with fortrabbit. ## Preparations You should first create a fresh App on fortrabbit. You could also use an existing one, but it's simpler to start from the scratch. Now you have to setup a repository on [Github](https://github.com) or [Bitbucket](http://bitbucket.org/). Best name it the same as your App on fortrabbit… or however you can remember it best. I'd recommend to use a private repo, as long as you don't plan on going public with your source code. I'll go with Bitbucket in this example, 'cause they offer (a limited amount of) private repos for free. ## Setup Codeship Now you can sign in to codeship with your Bitbucket (or Github) account and create a new repo. ![Create project](/blog-assets/img/create-project.png) Following the create link you can choose your repository provider. I went with Bitbucket and chose my `my-app` repository. ![Choose repo](/blog-assets/img/select-repo.png) In the next screen of the setup process codeship tells you how to set up your hook. Follow the instructions and make a first commit and push to your (Bitbucket) repo. ![Setup hook](/blog-assets/img/setup-hook-1.png) Now you need to choose the _Technology_, i.e. your test environment. Choose _PHP_ in the top select bar. If you need (I didn't) modify the setup and test commands. ![Setup hook](/blog-assets/img/choose-technology.png) ## Setup your fortrabbit App You need to install your codeship project's SSH key in your fortrabbit App so that codeship will be allowed to push to fortrabbit. You can find the key in the _General_ tab of your project's settings. ![Get SSH key](/blog-assets/img/get-ssh-key.png) Copy and paste the key as a new user in the _Git_ tab of your App on fortrabbit. ![](/blog-assets/img/save-ssh-key-with-fortrabbit.png) ## Setup deployment: codeship -> fortrabbit This is final step. Go again to your project settings on codeship and open the _Deployment_ tab. Choose _$script_ from the buttons and enter the following in the deployment command (modify according to your App's Git URL and App name): git remote | grep -q frbit-master || git remote add frbit-master git@git1.eu1.frbit.com:my-app.git git push frbit-master master It should look alike to (the textarea breaks the lines, but it should be two, not three): ![Setup deployment](/blog-assets/img/setup-deployment.png) ## Commit, push, test and deploy Well, you did it. Now just do you first code, test & deploy cycle. For this you need of course something testable. Here is a [demo app](/blog-assets/archives/testable.tar.gz) you can use if you haven't one at your fingertips. Add your code, commit everything and push (to Bitbucket): $ git add -A $ git commit -am 'Test and deploy' $ git push On codeship, you should see something like this: ![Test and deploy](/blog-assets/img/deployment-log.png) And on fortrabbit, your code has been deployed! ## Going multi stage No problem. With codeship, you can setup a different deployment script for each branch. So assuming you followed our [multi stage guide](http://fortrabbit.com/docs/in-depth/multi-stage-environment) and read the extension about [CI and multi-stage](http://fortrabbit.com/docs/in-depth/integrating-external-ci#how-to-use-it-with-multi-stage), just modify the deploy script on codeship for each branch like so (of course: replace the actual App Git URLs): **test branch** git remote | grep -q frbit-test || git remote add frbit-test git@git1.eu1.frbit.com:my-app-test.git git push frbit-master refs/heads/test:refs/heads/master **stage branch** git remote | grep -q frbit-stage || git remote add frbit-stage git@git1.eu1.frbit.com:my-app-stage.git git push frbit-master refs/heads/stage:refs/heads/master **prod branch** git remote | grep -q frbit-prod || git remote add frbit-prod git@git1.eu1.frbit.com:my-app-prod.git git push frbit-master refs/heads/prod:refs/heads/master * * * **Disclaimer**: Of course [wercker](http://wercker.com/) and [Codeship](https://www.codeship.io/) are not the only "Continuous Integration as a Service" providers. You might also have a look at [CircleCI](https://circleci.com/), [TravisCI](http://travis-ci.com/) or others. [fortrabbit](http://fortrabbit.com) is definitely also not the only place to host your PHP application, but maybe the coolest. Don't forget to check out our [big list of developer facing services](https://docs.google.com/spreadsheet/ccc?key=0An6rx68cKNFNdDNYdFdSSTNzZXl5eGRSY0ZxSW10aHc#gid=1). # Introducing 2FA Source: https://blog.fortrabbit.com/introducing-2fa Created: 2015-06-18 Author: Frank Lämmer Tags: chronicles, changelog > Two-factor authentication arrives for fortrabbit accounts, together with configurable session and sudo timeouts. ## Two-factor authentication and extended session time are here Go to your fortrabbit Dashboard, visit your Account and enjoy the new optional security settings we have just added: * Secure your fortrabbit Account with two-factor authentication * Modify the session time and the SUDO time We assume you know [what 2FA is](https://en.wikipedia.org/wiki/Two-factor_authentication) and how to use it in general. This is our journey to 2FA. ## Convenience VS security We virtually fight over security and convenience sometimes. Security is MOST important for us as a hosting provider of course — see our [help article](http://blog.fortrabbit.com/security) — but I personally don't believe that more security necessarily always means less convenience. These new settings here are in good balance. You can boost your Account's security on fortrabbit while also increasing convenience (don't get kicked out all the time). ## Modify session times There are two fortrabbit Dashboard sessions: 1. How long you stay logged in 2. How long it takes until you'll be asked for your Account password (and 2FA if enabled) to perform a "critical action" Both timings can be edited and extended now. Please mind that we don't allow a permanent login for security reasons. ## How we have implemented 2FA This is the is the initial release. We will add additional improvements over time. ### Software implementation only - no SMS We had bad experience and therefore don't trust SMS all that much — they can be redirected or sniffed with far less effort than you probably think. Also SMS takes a while until they reach your cell phone. Also: it takes extra efforts to build some SMS sending system and we rather wanted to launch 2FA sooner than later. Our 2FA implementation works with TOTPs (Time-based One-Time Passwords) — in other words: you'll need an extra (mobile) app that can derive those codes from a secret (QR code). The usual suspect here is Google Authenticator; available for [iOs](https://itunes.apple.com/en/app/google-authenticator/id388497605?mt=8) and [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en). ### Recovery codes When setting up 2FA you'll get backup codes which you can use if you loose your device. Save those very safely. Print them out or put them in a secured file fault. As of now, it's the only way to access your Account if you enable 2FA and can't access your device anymore. ### No "remember me" on this device So far you have always to enter the "2FA code" when logging in to your Account. Google, for example, only asks you once per device (if chose so). We're currently thinking about providing this as well. One at a time. ### Saying no to social logins We had plans to bring social logins to fortrabbit — think login with your GitHub or Google account. Enhancing our own Account security now pushes that back. ### Team security 2FA should be a team policy, of course. When you visit your Company settings you can see which of your team members have enable 2FA already. ## Enhanced session CSRF handling This release also includes an enhancement around the way we handle sessions — reported by our favorite security consultant Mayank Bhatodra. ## Will you make use of it? I am curious how many clients will actually use 2FA. # fortrabbit agent skills — early preview Source: https://blog.fortrabbit.com/introducing-agent-skills Created: 2026-04-28 12:00:00 Author: Frank Lämmer Tags: chronicles > An early preview of fortrabbit agent skills: plain-text instruction files that teach AI coding assistants how to manage apps. ## What are agent skills anyway? It's a new shiny thing. AI coding assistants, like Claude and OpenAI Codex, know a lot about development already. But they can also be extended with domain-specific knowledge. A skill is a Markdown file that tells the agent how to operate in a given context. Think of it as documentation written for a machine rather than a human, but readable enough that a human can follow along. Often, you'll create your own agent skills so the tool knows your best practices. But ready-made skills also exist, for example: ## The new fortrabbit agentic skills See the [fortrabbit skills repository on GitHub](https://github.com/fortrabbit/agent-skills) and the :ContentLink{text="agent skills docs" prefix="docs" href="/platform/automation/agent-skills"} for the full command reference and configuration options. Try them out right away: ```shell curl -fsSL https://raw.githubusercontent.com/fortrabbit/agent-skills/main/install.sh | sh ``` This will install the skills in your local user agent config folder. They can also be installed on a per-project basis and also using the GitHub command line client `gh`. See the [repo](https://github.com/fortrabbit/agent-skills) for more install options. ![fortrabbit skills with Claude](/images/fortrabbit-skill-with-claude.png) Then, open your agent and type `/fortrabbit` and follow along. They can also be invoked by natural language, like when mentioning `deploy this to fortrabbit`. ## What it does The current skills cover core operations: - Deploy code via Git or rsync - Sync databases up and down - Handle content syncs for CMS setups - Work through common Craft CMS workflows — similar to what Craft Copy handles today, but not tied to Craft CMS fortrabbit supports several deployment modes: pure Git, rsync, or a hybrid where code ships via Git and user-generated content syncs via rsync. The instructions cover these different setups rather than assuming a single workflow. The skills are also reasonably failure-tolerant. If a step fails, the agent can identify what went wrong and often suggest an alternative route. ## What thrills me **Already useful today.** I hope this will become popular for users during onboarding and initial setup. Getting a fresh local project connected to fortrabbit — credentials, SSH keys, deployment method, environment variables — is where many new users drop off. This can cut through the chicken-and-egg problem: test the platform without already having a project ready, but without compromising too much. We never liked the idea of one-click installers, where you end up with generic code on the server but nothing running locally. An agent that knows fortrabbit can walk you through setup interactively. Set up a project in your local development environment, run a deployment, see it work on the remote. ## What worries me **Dangerous operations.** Some tasks an agent can trigger — overwriting a database, deleting files — are destructive and hard to reverse. The skill instructions are written to be careful, but agents can and do misread context. **Hallucinations.** While testing, Claude couldn't always work around unexpected problems — sometimes it created new ones. A skill file narrows the surface area for errors, but multiple times it confused old platform with the new platform config. **Maintenance burden.** The skill files are effectively a second version of our user documentation in a different format. Keeping them accurate as the platform evolves is real work, even when we generate them. **So many standards.** The agent skills space is moving faster than JavaScript frameworks. As far as I know, at the time of this writing, there's no npm or Packagist equivalent for skills — no common registry, no agreed versioning. GitHub is [adding skills management to their CLI](https://github.blog/changelog/2026-04-16-manage-agent-skills-with-github-cli/). Cloudflare is proposing a [`.well-known` discovery standard](https://github.com/cloudflare/agent-skills-discovery-rfc). There might be different marketplaces. These may converge or they may not. We're shipping against that uncertainty. **Implicit prose in Markdown.** Instructions are human-readable, the agent interprets them with some latitude. Part of me wants them to be far more explicit and structured. I'm still working out where that balance should be. The [agentskills.io](https://agentskills.io/home) website suggests not cross-referencing, and repeating important information instead, to save on token usage. My instinct is more DRY. ## A bigger threat **A double-edged sword.** The technology is impressive. But it is also an immense stress test for our business. At fortrabbit we aim to make hosting fun for humans. I am proud of what we have built. Yet some of the paradigms agents may make us less relevant: headless hosting, infrastructure as code, AI-generated configuration. Setting up a `docker-compose.yml` is no longer a dark art. Part of what we solve is simply not that hard anymore. ## What's next The skills will become much more useful once we have a proper API and CLI on the fortrabbit side for the new platform. We will get there. Right now, most of what the agent does goes through SSH and Git — functional, but limited in scope and a bit fiddly. We're also considering splitting the current skill into smaller, more focused skills for different use cases. And we're tracking the discoverability standards to make sure the skills can actually be found by agents that need them — once that landscape settles. For OpenAI Codex, dedicated testing is in the works. ## Try it and tell us Install the skills, try deploying a project with your AI assistant, and let us know what happens. What worked, what confused the agent, what's missing — all of it is useful. It will directly shape where this goes next. ## Side notes Agent skills are a relatively new feature. It will evolve. It's crazy, how all players want to be in the pole position. - Microsoft integrated SKILLs discovery with gh client - Cloudflare pushes automatic discovery via .wellknown - Anthropic is a bit sleepy about their market place - Custom market places pop up: [agentskills.host](https://agentskills.host/en), [getagentskills.com](https://www.getagentskills.com/), [skillpub.net](https://skillpub.net/) # Introducing Craft Copy Source: https://blog.fortrabbit.com/introducing-craft-copy Created: 2018-11-01 Author: Oliver Stark Tags: webdev > Craft Copy, an open-source command line tool that syncs code, assets and the database between a local Craft CMS and fortrabbit. ![](https://raw.githubusercontent.com/fortrabbit/craft-copy/master/demo_setup.gif) **TLDR; Check it our yourself: [github.com/fortrabbit/craft-copy](https://github.com/fortrabbit/craft-copy)** ## Who is it for? It's a helper tool for all fortrabbit clients [running Craft 3 in a "sophisticated way"](https://help.fortrabbit.com/craft-3-about#toc-modern-workflow): Having a [local development environment](https://help.fortrabbit.com/local-development) setup, [deploying the code base with Git](https://help.fortrabbit.com/craft-3-deploy-git), [syncing assets with rsync](https://help.fortrabbit.com/craft-3-assets-uni), [authenticating with an SSH key](https://help.fortrabbit.com/access-methods#toc-ssh-key-authentication), being familiar with the command line. ## What does it do? It's basically a wrapper for `mysqldump`, `git` and `rsync` (all are required locally) — also including some magic. It connects your fortrabbit App with your local development environment. Deploying with Git is convenient at fortrabbit, but it's only part of the deployment. This tool helps with all the other parts: ### Setup help It will check if your setup is complete or if certain parts are missing. ### Database sync Craft Copy helps you keeping the databases in sync. You can easily sync the database up (from your local dev env to production at fortrabbit) and down (from production at fortrabbit to your local dev env). ### Assets sync And you can sync the assets — think uploads — with rsync up and down. ## Only for fortrabbit? Yep, sorry. Currently only fortrabbit is supported, as this is a standardized environment. Craft Copy is also still in BETA. Please contribute! ## That's it? No! Craft Copy is under development and still in BETA, `v1.0.0-beta5` is the current version as of this writing. Craft CMS 3.1 will feature better multi-staging support and Craft Copy will make use of that. There also will be options to run additional scripts before and after the `copy` commands. The most common use case is frontend assets (JS & CSS) compilation. So please keep an eye on that. ## Anything else? Thanks to the testers and early adapters for sharing feedback and [issues on GitHub](https://github.com/fortrabbit/craft-copy). More help always welcome. ## Where is it? **[github.com/fortrabbit/craft-copy](https://github.com/fortrabbit/craft-copy)** # Introducing password authentication + dynamic help Source: https://blog.fortrabbit.com/introducing-password-authentication Created: 2016-07-21 Author: Frank Lämmer Tags: chronicles > Password authentication as an alternative to SSH keys, plus documentation code examples that fill in real values while logged in. **This is new**: Just use your Account password, when you have trouble setting up SSH keys. Copy/paste actually working code examples directly from our documentation. See the [help article](https://help.fortrabbit.com/access-methods) on how to do it. ## The story behind the new features **Less initial complexity** is one of our current goals, as stated in the last [mission statement](/mission-statement-2016). When examining our conversion funnels, we saw big drop off rates after the signup. It turned out that we have overlooked some important details: ### Hidden SSH key setup barrier SSH public key authentication is more secure and more convenient. Our assumption was: the majority of our users already have a GitHub or Bitbucket account and thus already have SSH keys setup with their local system. But what we haven't noticed: SSH key setup on Windows is fairly complex. Our team uses Linux & Mac OS - too easy to oversee. Interestingly, the big players have reacted on this problem: SSH keys authentication is not a requirement to use GitHub and Bitbucket - anymore. They even reduced the complexity by promoting SSH password authentication and providing in browser-editing-GUI and even desktop GUIs to store the login credentials. In consequence, SSH key setup was one of the most frequent support requests. With the new Intercom chat we could see that most requests came in fact from Windows users. So we have re-edited our [SSH key documentation](https://help.fortrabbit.com/ssh-keys) on this, time over time. We moved from "here are all your possibilities" to a more opinionated "this is how to do it". It was still hard for Windows users, especially for novice ones: When you Google "[SSH key setup windows](https://www.google.de/search?btnG=1&pws=0&q=SSH+key+setup+windows)" you will get instructions for PuTTY, which is all fine, but to make PuTTY working with fortrabbit you need to know where it stores it's SSH keys. Now we give up on this - SSH keys are no longer required to use fortrabbit. We are introducing password authentication on Account level and it is enabled by default. So when boarding, users will no longer be asked for their SSH keys, instead they can simply create their first App right away. --- **Wait a minute - what have we done?** Our aim with new password authentication was to reduce initial complexity, but it turns that this also introduces a new kind of complexity. There are two ways now to do things here, so we need to show two different code examples in the documentation on how to deploy and interact with the services. --- ### The new dynamic code examples in the documentation And this why we are also introducing a new way to read our [documentation](https://help.fortrabbit.com). When you have an account with fortrabbit (and are currently logged in), you will see dynamic code examples tailored for your App. In other words, you don't need to replace any example strings any more, you can copy/paste the code snippets right away. What you will see depends on your the SSH authentication method of your Account. There is also a chooser to select among your Apps for which you want to see the code examples. ![Live code examples](/images/live-code-examples.png) **[Try it out yourself](http://help.fortrabbit.com/access-methods#toc-the-code-example-helper)** (you'll need an Account with Apps) ### More details We have also updated our documentation to match with the new authentication methods. The progress is still ongoing. With this update we also included some changes to our deployment Nodes. The tunnel services changed (new URLs, see our [status update](http://status.fortrabbit.com/incidents/7n4nmn4695hm)) and there is a new shorter URL schema available for deploying, the old one still works. The new features are available for New Apps (new stack) only. **What does this mean for existing Accounts?** Nothing. If you have a fortrabbit Account and prefer to use SSH password authentication just remove all SSH keys from your Account. If you choose to stick with public key authentication just do nothing. So far the **theory**, let's see how it works in **reality**. # Introducing Upper Source: https://blog.fortrabbit.com/introducing-upper Created: 2018-08-16 Author: Oliver Stark Tags: webdev > Upper is an open-source Craft CMS plugin that wires a pull CDN — Cloudflare, Fastly, KeyCDN — into the CMS as an edge cache. **TLDR; Check it our yourself: [github.com/ostark/upper](https://github.com/ostark/upper)** ## Who is it for? It's for every Craft developer — not limited to fortrabbit hosting — who wants to integrate a pull CDN. So, you basically already have an account with Cloudflare, Fastly, KeyCDN or alike and Craft running in production somewhere. Now you want files to be cached and delivered by the CDN. This Craft CMS plug-in adds the magic. ## What does it do? ![](https://github.com/ostark/upper/blob/master/resources/response-header.png?raw=true) It adds `Cache-Control` and `XKEY/Surrogate-Key/Cache-Tag` headers to your pages. It also takes care of the cache invalidation, when entries or sections get updated. Need a fresh-up? Check out our [Mastering HTTP Caching article](https://blog.fortrabbit.com/mastering-http-caching). ## Why should I care? ![](https://github.com/ostark/upper/blob/master/resources/preformance.png?raw=true) It helps making your page load much faster. ## How can I use it? You get it by Composer, you install, configure and activate it. For more, see [the README](https://github.com/ostark/upper#the-pep-pill-for-your-craft-site). # Introducing the 'client invite' Source: https://blog.fortrabbit.com/invite-the-client Created: 2017-06-15 Author: Frank Lämmer Tags: changelog > The client invite hands billing for an app to the client, instead of sharing logins or asking for their credit card details. In the PAST: you might have shared hosting account usernames and passwords or asked clients for their credit card details to setup payment. Sounds familiar? You can do better NOW: ![Client invite button](/images/client-invite-button.png) ## 1. Invite the client to take over billing Transfer ownership directly to a client — or the boss of the agency. It's only a few clicks in the Dashboard. They'll be invited to setup a Company to pay for the App. It's a smooth flow — designed for your non-techie client (but it works for techies as well). And YES: It also works for Apps that are still in trial mode. ## 2. Retain access after transfer Websites and application are never done. There is always something to do. That's why you will — by default — keep access as an Admin on the App you have transferred. You can still see and edit the App in your fortrabbit Dashboard. Everything remains exactly the same — except the client is paying the bill now. ## 3. Proceed from here We are just getting started. Now the real fun begins: ### Working on multiple projects for one client You not only can access code, change settings and scale the initial App, as an Admin of a Company you can also create new Apps on behalf of your clients Company. ### Working with multiple clients You can of course repeat this with other clients. Login once, manage many: All Apps you can access are listed with your personal Dashboard Account. Your own projects and your client work. You can also move Apps between Companies. ### Quitting made easy ![Client web developer relation](/images/client-developer-relation.gif) **Sometimes clients just suck.** So we made it easy for you to exit at any time: When the work relationship with your client is ending: leave the Company in the Dashboard. This will hide the App from your Dashboard and disable your code access. This works both ways of course: Clients are in control of billing and team, so they can also cancel your Admin assignment at any time. Cancellation is handled in a clean way, no need to reset passwords. ### Collaborating in bigger teams This is still not all. The freelancer/client relationship is just one use case. Our powerful collaboration features enable you to match nearly any real world work relationship — freelancer, digital agency, startup … There can be multiple Owners. And you can also invite contractors to share only specific Apps. --- ## Other changes with this update - The standard trial time has been extended - The "Company xs" plan includes two team members (to make this more attractive) - Dashboard: A little style rebrush - Dashboard: Choosing & changing access roles simplified - Dashboard: Companies now shown on the Dashboard Home - Transactional e-mails: Style update, wordings and nice looking buttons - Bug fixes & stability updates --- ## Why we are doing collaboration this way We get feature requests for white-label reseller hosting on a regular basis. We know that web developers take care of all stuff related to the website, from web-design to web-hosting, so they want to offer it under their own brand. We believe that we can help web developers better with this transparent collaboration solution. A separation of responsibility is key here. We are responsible for the hosting, while you can focus on crafting great applications. Imagine an unexpected down-time. We are responsible and we will deal this with the Owners. So, please stop cramping your VPS with client projects. --- Thanks for reading so far, we are curious for your feeddack and will reply. Are you missing something, like a bonus for every transferred client? # Laracon observations Source: https://blog.fortrabbit.com/laracon-observations Created: 2013-09-02 Author: Frank Lämmer Tags: opinion > Notes from Laracon 2013 in Amsterdam, on the relationship between Symfony and Laravel and where the PHP framework scene was heading. ## We've been to Laracon What happens when you gather together some of the most influential PHP framework developers? The Laracon conference in Amsterdam was the answer to this question. ### Symfony Laravel relationship It surprised me a bit, when I saw Symfony creator [Fabien Potencier](https://twitter.com/fabpot) even before the Laravel author [Taylor Otwell](https://twitter.com/taylorotwell) on the speakers list. I never really thought about the relation between Symfony and Laravel. Laravel uses Symfony components, sure, but where is the connection? Isn't there some kind of competition going on? On the first day there was a spontaneous Q&A session with Taylor, and he was asked just that: _How are you connected to Symfony, is there an official partnership agreement?_ His answer was along the lines of: _Well, actually we just use their components, but we don't really contribute back._ I was wondering how Fabien felt about this? Later on I was surprised to learn from Fabien that this is actually part of his plan. He has decoupled his framework into single, stand-alone components, so that other projects can easily leverage them as their building blocks. Drupal8 is another good [example](http://symfony.com/blog/symfony2-meets-drupal-8) for this. The idea is simple: Why should each framework reinvent the wheel for certain problems that are already solved in a great way elsewhere? This way the Laravel core team can focus on what they are really good at. The other big benefit is of course compatibility: With many frameworks using, say, the [HttpKernel](https://github.com/symfony/HttpKernel) component, you already know how it works. So if you start a Drupal (8) project tomorrow, you already understand the core, if you've worked with Laravel or Symfony before. Of course, without [Jordi Boggianos](https://twitter.com/seldaek) work resulting in Composer - the middleware, if you will - all of this would not have been possible. We are really excited about all this and curious where this all will lead to in the future. Maybe we'll see more specialized "meta" frameworks, solving edge cases, 'cause they become even more easy to build? Maybe even real standard components, outside the PHP core, which everybody uses so that you can rely upon them? ### On event organisation Thanks again to [Shawn](https://twitter.com/ShawnMcCool), [Jereon](https://twitter.com/JeroenGerits) and the whole Laracon team: You really did a great job! We have had a blast! I really liked the format of the conference. The location was great and everything worked just smooth and flawless. Even the WiFi didn't broke (very much). The ticket price was not too high and not too low. Cheaper tickets would have allowed more people to attend, which would have been maybe very nice, but on the other hand maybe more noisy and stressy for everyone. This way it was a very intimate atmosphere under high professionals. ### More impressions [Ben Rey](http://twitter.com/bjmrey) did a very nice summary of [day 1](http://storify.com/bjmrey/laracon-europe-amsterdam-30-31-august-2013) and [day 2](http://storify.com/bjmrey/day-2-laracon-europe-amsterdam-30-31-august-2013) with many tweets, quotes and slides. See [photos from Jordi](http://www.flickr.com/photos/seldaek/sets/72157635332125877/) and [photos from Stefan Neubig](http://www.flickr.com/photos/emotional-stuntman/9642114207/) on flickr. Go Laravel! # Lee Tengum about offload.io Source: https://blog.fortrabbit.com/lee-tengum-about-offload-io Created: 2014-08-28 Author: Oliver Stark Tags: chronicles > An interview with freelance developer Lee Tengum about building offload.io, one of the projects hosted on fortrabbit. ## Lee Tengum Earlier this month we've reached 10k users. Digits are all fine, but real people with real projects are more interesting. We asked Lee to tell us about his latest project on fortrabbit: **Lee**: I'm Lee Tengum, aka [@thatleeguy](http://twitter.com/thatleeguy), a freelance developer from rural Cranbrook British columbia Canada. I work from a 80sq [backyard office](https://twitter.com/ThatLeeGuy/status/482659411186679808) which gives me the freedom to work when I'm feeling inspired and to hangout with my kids. I've been a perpetual "start up" guy for a while now, with [Pancakeapp](https://pancakeapp.com) being my most successful venture to date. I have to say though that the greatest asset Pancake has is Bruno and Matt, they look after the day to day operations allowing me to pursue these other projects. Being a freelancer is in essence a small accelerator of projects, which brings us to what we're here to talk about, [Offload.io](http://offload.io)! **Oli**: Why did you started the project? **Lee**: Every day designers and developers create items that are awesome. These may be full blown site design PSDs, a bash script to automate deployment or a side project in it's entirely that they just do not have time for. Normally these would sit in waste after being built as they're not well documented enough for the other marketplaces or lacking of an installer etc. For example, let's take a SaaS based side project, it has hundreds of hours put into it, does something really clever, has billing already integrated etc... It's just that the developer doesn't have the time to devote to getting users. If this were listed at the other marketplaces, you'll get questions along the lines of "How much revenue?" or "How much traffic" which will subsequently net you an offer of a fraction of it's value for the project without revenue and traffic. They're not interested in looking at what the app itself or how much of a head start that is, just the $$$. Further to that, let's say you built a bash script to automate migration of data that saved you 4 hours of manual work, another developer in that same situation would happily pay you an hour worth of time to save 3 hours. In the other marketplaces they'd price it at $5 and you'll have to support 1000s of buyers who will ask you "How do you FTP into the admin panel"... Or you could sell it a handfull of times, at a reasonable price to other smart (and vetted) people, which is what Offload will allow you to do. There's a huge problem in our industry right now, this race to the bottom if you will, it's time to compete on value and not just price. **Oli**: What's the state of your project? **Lee**: Offload is currently accepting new members and looking specifically for designers and developers who have premium items that they are looking to sell. ![offload.io screenshot](/images/offload-io-shot.png) **Oli**: Can you tell us a bit about technology? **Lee**: Ah yes, the fun stuff. Offload is built on [Laravel](http://fortrabbit.com/solutions/laravel-hosting) and uses Twillio, Stripe and a pleasant soup of other bits to make it all come together. For platform Fortrabbit was the only choice in my mind, in fact all my projects go here as I'm not interested in running the sysadmin side of things and you make it dead simple for me to do what I do, ship code. The time that I do not have to spend debugging server stuff is time I can spend writing code. **Oli**: Anything else? **Lee**: I still do not have a fortrabbit shirt... # Let's Encrypt root certificate change Source: https://blog.fortrabbit.com/lets-encrypt-new-root Created: 2020-11-26 Author: Frank Lämmer Tags: changelog > Let's Encrypt will change its root certificates. Learn how this might affect you as a fortrabbit client. ## How we use Let's Encrypt fortrabbit uses Let's Encrypt services to provide free TLS certificates. These certificates are required so that your App can be visited over a trusted secure connection using the HTTPS protocol. We generate and renew these certificates for all domains you route to our services automatically. ## What is happening now Let's Encrypt will start using a new root certificate. See the [original article](https://letsencrypt.org/2020/11/06/own-two-feet.html) for more details. ## Timing Let's Encrypt will start using a new root certificate from ~~the 11th of January~~ someday late January or February. That means if you create a new App on fortrabbit after that will directly use the new root certificate. All existing Apps automatically have their certificates renewed about every 3 months. Any certificate renewed after that will also use the new root certificate. ## Impact UPDATE 2021-01: As [noted by Let's Encrypt](https://letsencrypt.org/2020/12/21/extending-android-compatibility.html), older Android devices will now also be supported with this update. No action required. We expect that everything will continue to work smoothly. The date ~~The new root certificate will not work on very old versions of Android (the mobile Operating System from Google). For those older devices an error will be shown when visiting an App hosted on fortrabbit. As far as we understand this will probably affect less than 1% of total visits. But this will depend on your user demographics. Use an analytics service to find out more about possible impact on your Apps. If your business relies on users that will be impacted by this change, consider installing and maintaining your own certificate. We have a built in option for this as well. See our [HTTPS help](https://help.fortrabbit.com/https). Using Cloudflare to protect your domains might be another alternative. See our [Cloudflare article](https://help.fortrabbit.com/cloudflare).~~ # Quickly set up a local Craft CMS dev site with the DDEV development tool Source: https://blog.fortrabbit.com/local-craft-dev-site-ddev-development-tool Created: 2020-09-10 Author: Jascha Silbermann Tags: webdev > Set up a local Craft CMS development site with DDEV, the Docker-based tool that became our recommendation for local PHP work. ## Introduction ### The DDEV development tool A detailed introduction to DDEV was given in our previous [article on PHP development tools](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup#ddev). Maybe also check out the DDEV website at [ddev.com](https://www.ddev.com/). To quickly sum up: * DDEV is a Docker-based tool that **targets local PHP development**. * DDEV supports a number of popular **content management systems and frameworks**. * We can set up **DDEV with a standard LAMP stack for local Craft CMS** development. ### Installation requirements DDEV sits on top of Docker and **works on macOS, Linux, and Windows**. The installation will be shown for macOS. To install on Linux you can also use Homebrew on Linux; the steps will be almost identical. The same works for Windows, provided your system has the Windows Subsystem for Linux (WSL) installed. For this installation procedure, you will need: 1. Basic knowledge of the **command line**. 2. PHP and Composer installed on the host machine. 3. The **Homebrew package manager** installed. * Install Homebrew on [macOS](https://brew.sh/) * Install Homebrew on [Linux or Linux Subsystem for Windows](https://docs.brew.sh/Homebrew-on-Linux) ## Install DDEV to power your local Craft CMS dev sites First, we need to install DDEV on our machine. The first step is to install Docker Desktop. If you already have Docker Desktop installed you can skip this bit. One nice thing is that **DDEV tries to accommodate the Docker version** already installed on your system. Other dev tools are less well-behaved in that regard. ```shell # install Docker Desktop brew cask install docker # make sure to run the Docker App once before proceeding! open /Applications/Docker.app/ # otherwise the ddev installation will not work ``` Once we have Docker installed we need to **launch the app at least once** to complete the configuration. Next, we install DDEV using a custom homebrew “tap”: ```shell # add custom ddev tap brew tap drud/ddev # install ddev brew install ddev ``` If you're using a different operating system, or are uncomfortable using `brew`, check the official [DDEV installation](https://ddev.readthedocs.io/en/stable/#installation) instructions to find alternative means of installing DDEV. ## Set up a local Craft CMS dev site with DDEV In this section we'll show how to **set up a brand new Craft CMS site with DDEV** for local development. In case you want to use DDEV to power an existing local Craft dev site instead, please refer to our section [Using DDEV with an existing Craft CMS installation](#ddev-with-existing-site) below. ```shell # create and enter project directory mkdir craft-ddev && cd ./craft-ddev/ # use Composer to set up a Craft project composer create-project craftcms/craft ./ # when asked if you are ready to set up craft, answer no, we will do it later # create DDEV config ddev config # use the suggested defaults by hitting enter # (, 'web', 'php') # spin up the machine the first time ddev start # this will take a while (once) # once the machine is running we print out its settings ddev describe # note the network and database settings needed for the Craft setup # this will also show how to connect to your site in the browser after setup # log in to the running machine to set up Craft # without this, the database connection will fail ddev ssh # set up Craft from inside the machine # make sure to use the exact DB credentials as described from inside the container ./craft setup # and leave the machine exit ``` That's it. Now you should be able to **just access the URL shown via `ddev describe` in your browser** to visit your site. ## Using DDEV with an existing Craft CMS installation We've shown how to use DDEV to set up a fresh dev site for local Craft CMS development. Now you might be curious how to approach your existing local Craft dev sites. Maybe you've been using Homestead or Valet so far, or another PHP development tool. The good news is that it's really easy to **use DDEV to host your existing local Craft CMS dev sites** as well. Here's how you run an existing Craft site via DDEV: 1. Use `cd` to enter your Craft project directory 2. Once there, run the following commands: `ddev config` `ddev start` `ddev describe` 3. Edit your `.env` file to reflect the values shown by `ddev describe`. 4. Access the URL shown by `ddev describe` in your browser. You should be up and running with the Craft site showing in your browser. ## Deploy your local Craft CMS dev site You've gotten your local Craft CMS dev site up and running — great! But what's next? Likely, you'll want to deploy your local site to your hosting provider. So le'ts take a look at how to do that. For this example, **we use our fortrabbit platform and the [Craft Copy tool](https://github.com/fortrabbit/craft-copy/)**. With another tool and / or platform the exact specifics will differ. But the general concepts should be similar. ### Requirement: have your SSH key set up Here at fortrabbit, we care deeply about security. Which is why we require our users to **connect to our infrastructure using an SSH key**. This is contrast to logging in using a username-password combination. To sync your local dev site to fortrabbit, you'll need to: 1. Have a public-private SSH key pair set up on your local machine. 2. Have the public key part connected with your fortrabbit Account. If you're unsure about this, see our help pages for a [detailed instruction of how to set up the SSH key](https://help.fortrabbit.com/ssh-keys). ### Deploy a Craft CMS dev site to fortrabbit using Craft Copy Once the SSH key is set up, we'll **configure DDEV to use the keys** from your local machine. This will allow us to use Craft Copy from inside the container. Just follow the steps outlined below: ```sh # Make local SSH keys available inside the container # ( Needs to be done each time you restart your machine ) $ ddev auth ssh # Login to the DDEV container $ ddev ssh # Now, in the container, install and setup Craft Copy # Required to get rid of PHP 7.0 for any Craft CMS lower than 3.6 $ composer config platform --unset # Include Craft Copy via Composer $ composer require fortrabbit/craft-copy -W # Update dependencies first $ composer update # Install the plugin with Craft CMS $ php craft plugin/install copy # Initialize the setup $ php craft copy/setup # This will guide you through the steps and also run the initial installation # Later on you can run the Craft Copy commands: $ php craft copy/code/up $ php craft copy/db/up $ php craft copy/volumes/up ``` ## Conclusion In conclusion, **DDEV is a great choice for local Craft CMS development**. DDEV can be used to quickly set up a new Craft CMS dev site and works just as well with your existing sites. What's even better, DDEV plays nicely with Craft Copy. In case you're already running Docker on your machine, having a local Craft CMS dev site powered by DDEV is just 15 minutes away. We recommend you give DDEV a shot! # Logs now available in the browser Source: https://blog.fortrabbit.com/logs-in-the-browser Created: 2026-07-21 Author: Frank Lämmer Tags: changelog > Read PHP, access, Apache, and Jobs logs right in the dashboard. Filter, follow live, download — no SSH required. ## The importance of server logs You experience slow load times, error pages, or the white screen of death. Most of those issues are code- or config-related and we are happy to help. **What does the log say?** This is the first step in troubleshooting. But it's not something every PHP developer is comfortable with — we know this from support. ## Meet the new browser logs Design for failure. The browser-based interface makes it easy to explore logs without much effort. It has some nice features like log filtering, real-time updates, IP look up and linked documentation. It looks nice in dark and light mode and with all of our color themes. ![The log viewer in the dashboard](/images/log-screen.png) Logs are available in the **Logs** tab of each environment, in the new dashboard. :BlockLink{title="See logs for {{app-name}} / {{app-env-name}}" path="/environments/{{app-env-id}}/logs"} ### Log sources ::ContentClip{src="/images/logs-sources.mp4" poster="/images/logs-sources.png"} :: - **PHP log** — uncaught exceptions, fatals, warnings, notices. - **Access log** — one line per request: method, path, status, IP, user agent. - **Apache error log** — rewrites, permissions, denied access. - **Jobs log** — PHP output from workers and scheduled commands. The sources map to the layers a request passes through, so the failed page and the reason behind it often sit in different logs. ## Filter and follow - Filter by level, or by method and status for access logs. - Click an IP to filter for it, or look it up on `ipinfo.io`. - Free-text search across visible lines. - Pick a time range — today, yesterday, or a custom day and hour. - Follow live to watch new lines arrive. - Load more to page back through history. ## Download logs from the browser ![The download panel](/images/logs-download.png) While the browser is a great way to get a quick view of your logs, you may need the raw file for a deeper look. Switch to **Download**, pick a source and a range, and a link is mailed once the export is ready. Larger ranges take a few minutes to prepare. ## Keeping the tail command around We'll keep `frbit-tail-logs` around for a while. But we may kill it in the future. ## New log docs We gave the docs a pass while we were at it. - :ContentLink{text="Logs docs" href="/platform/settings/logs" prefix="docs"} - covers each source, filters and more. - :ContentLink{text="Apache error codes" href="/dev/learn/apache-errors" prefix="docs"} - the `AHxxxxx` codes, and how to read them. - :ContentLink{text="HTTP status codes" href="/dev/http-status-codes" prefix="docs"} - what a 500, 503, or 504 in the access log actually means. ## Costs The new log browser is free to use and included with all plans. ## State We are kindly asking customers to try it out and provide feedback. This feature will need to grow; we'll learn and iterate. But we need actual data and experience with live websites now. ## Outlook We have two major observability features planned: **Metrics** will extend the logs with empirical data, shown as graphs and charts. **Events** will record all user interactions and events. We also have ideas to extend the log viewer with an export option, to send a stream of logs to a third-party service. But we are also working on automation and improved agentic workflows with a public API and MCP. We are also working on small improvements and bug fixes, step by step, getting closer to a production-grade state, ready for public release. --- - [About logs](/platform/settings/logs) # The perfect PHP platform manifest Source: https://blog.fortrabbit.com/looking-for-the-perfect-php-hosting-platform Created: 2012-09-06 Author: Oliver Stark Tags: opinion > A manifest for what a PHP platform as a service should do, written in 2012 when none of the existing ones came close to it. About 18 months ago the first players in the PHP Platform as a Service (PaaS) market got [some](http://clouduser.de/news/cloudcontrol-ist-live-5907) [media](http://techcrunch.com/2011/05/10/paas-php-fog-launches-to-the-public/) [attention](http://techcrunch.com/2011/08/23/engine-yard-acquires-orchestra-to-add-php-support-to-its-paas/), but they were far away from a perfect solution. At the same time our own hosting environment also wasn't satisfying in terms of deployment tools and scalability. So we started to collect ideas to improve our existing platform and ended up taking a big step forward a few months later: * Replacing our own hardware with AWS components * Completely rewriting 200K lines of codebase * New slim & extendable product structure * Strong focus on developer's needs ## Fortrabbit Manifesto ### for the perfect PHP Platform #### Serve a fully managed & optimized stack * An extended maintenance-free LAMP stack * Bootable with a single click in seconds - a no-brainer * Stick to the latest stable versions (Apache 2.2 + PHP 5.4.6 at the moment) * A high level of security #### Provide a functionally complete & flexible environment * Configurable settings (via GUI or ini_set()) * Comprehensive set of PHP libraries * Scalable in any dimension (PHP/Database, Cache size, Multi-Level-Deployments) #### Make the deployment process easy & fast * As quick as possible (push to deploy - done in seconds) * Stick to standards: GIT, SSH & (S)FTP * No proprietary tools/workflows #### Provide tools for monitoring & analysis * Whats going on with my App? Is it healthy? Idle? Slow? And why? * And what can i do to make it perform better? #### Give awesome support * Fast useful responses to support requests * Full documentation * Communication at eye-level #### Offer it for a fair price * For the individual developer: with a small weekend-project * For the startup/company: with the need of scalibility & high availibility * For us: to pay the infrastructure and manpower to maintain & extend the service This outlines our general philosophy for providing the service. Stay tuned for the second post where I go into more detail about how we're building a product following this manifesto, and why we're focusing on PHP rather than providing a platform that supports more programming languages - at least for the moment. # Market overview: CDN services Source: https://blog.fortrabbit.com/market-overview-cdn Created: 2017-08-03 Author: Frank Lämmer Tags: webdev > An opinionated field guide to developer-friendly CDN services, with pay-as-you-go pricing that finally fits medium-sized projects. ## A generation of CDNs for developers Not so long ago, Content Delivery Networks was only for the enterprise only. Now, there are more offers for developers and medium projects — with pay-as-you-go pricing and additional features. As a web developer you have an overwhelming choice of services. This post helps you through the jungle to find the best performance and security optimization tool for your needs. ### When to use a CDN CDN is cool tech to play with. But mind that for many websites and applications it might be overkill. Keep your tech stack simple. Additional features come at the cost of additional complexity (like cache invalidation) and additional points of failure. CDN benefits are: - Increased speed: especially for distant visitors - Optimization: by offloading (less CPU, traffic & storage) and better delivery Rule of thumb: Consider a CDN when you have a few thousand requests per hour and you are serving a lot of static assets. The most common use case is to serve images. ### How a CDN works The basic idea is this: Websites are global, visitors are local. Content is delivered faster, when served from a server closer to the visitor. The more points of presence, the closer, the better. So the visitor should get the heavy (static) assets — mostly images, but also JS, CSS, fonts and maybe even cached versions of full pages — from a nearby server. That reduces latency and round-trips (RTT). And that also helps with performance as it offloads requests from the application web server. ### How implement it So you do something like this … ```html ``` … and the CDN will distribute the Cheshire Cat to multiple locations around the world. #### Push & Pull You might ask yourself, when and how are these images uploaded to the CDN? Classical CDN are working as **push CDN**s, so it's actually your responsibility to upload the assets to the CDN. The benefit is that you have a good control about your media. All the cool kids are using **pull CDN**s (reverse proxying). Why? Because it adds on top: The images are uploaded locally and then pulled to the CDN "automagically". Please see our extended [post about HTTP caching](https://blog.fortrabbit.com/mastering-http-caching) & how to implement a pull CDN. TLDR: You'll easily find plug-ins for your CMS and example configs for your framework. ### Additional services CDN functionality is only one part of performance and security. Often also included with a hosted service: - Image optimization - Image conversion to webp - Cache header optimization - Cache purging (when you have changed a file) - DDOS protection - Web Application Firewall - GZIP (& brotli) compression - JS & CSS file bundling - CSS & JS minifying & concating - HTTP/2 delivery - TLS (SSL, https) - Statistics - Video streaming - (Static hosting) - API - … All this correctly combined can really help to fasten up things. But don't forget: clean code is the best base for a fast website. Keep your stuff slim (also see our [application design guide](https://help.fortrabbit.com/app-design-pro)) and avoid the [website obesity](http://idlewords.com/talks/website_obesity.htm). And of course you know: Decreasing page load time can increase conversions, sales and even SEO. ## CDN providers We are using [keycdn](https://www.keycdn.com/) from Switzerland, which is popular among devs. Other developer-friendly CDN providers are [fastly](https://www.fastly.com/) and [cdn77](https://www.cdn77.com/). MaxCDN and Highwinds recently joined [StackPath](https://www.stackpath.com/). IaaS users might have a look at [Cloudfront (AWS)](https://aws.amazon.com/cloudfront/), [Azure CDN](https://azure.microsoft.com/en-us/services/cdn/) or even [Google Cloud CDN](https://cloud.google.com/cdn/). Enterprise clients might have look at [Akamai](https://www.akamai.com/), the [enterprise CDN by IBM](http://www-03.ibm.com/software/products/en/enterprise-content-delivery-network-ecdn) or [GlobalDots](http://www.globaldots.com/). **[cdncomparison.com](http://cdncomparison.com/)** by betahex is an almost up-to-date table of CDN providers with all features. ### Special mention #### Cloudflare [Cloudflare](https://www.cloudflare.com) is the popular choice. It is a suite of services with a lot of "magic". It's plug and play: You point (DNS) your domain to Cloudflare and that's it. ClouFlare got a bit of bad rep when [some HTTPS pages where found in the Google cache](https://news.ycombinator.com/item?id=13718752). It has a free plan for personal use and of course a WordPress plugin. I personally like to have some more control about certain aspects, so I haven't used it yet. #### greta.io [greta.io](https://greta.io/) is a (new) startup aiming to "revolutionize" data distribution — even with P2P (?!). They have a "headless" setup to integrate the service with just a little javascript — totally free and without the need of an account. A unique feature is that images are "lazy loaded". I have integrated the service here on our blog. Check out the [post list page](/) - it will load the images when you scroll down. Inspect it in your browser dev tools to see what's going on. ![Lazy loading images](/images/cdn-scrolling-lazy-load.gif) Above: greta lazy loading in action. ### Image processing and CDN services As mentioned: In most cases, those images (of cats) are making your website heavy. So I like to include image delivery services under this topic as well. In fact, they usually come with an integrated CDN + all the magic you want for your images. Image transformation (crunching image uploads for web delivery) can be outsourced to free up CPU power. ImageMagick — for instance — can be resource-hungry and it usually runs on the web facing server, so your visitors might have to wait a little longer while crunching is in progress. Imagine an URL-API for image sizes like `/img/w_400,h_400/cat.jpg`, so there is no need to define thumbnail and preview sizes upfront. You can change that with the design. Responsive images are easier to setup as well. Less work for your framework or CMS, more magic in the background. [Cloudinary](http://cloudinary.com/) and [imgix](https://www.imgix.com) are the biggest providers in this space, followed by: [Transloadit](https://transloadit.com/), [libpixel](https://libpixel.com/), [Filestack](https://www.filestack.com/), [Blitline](https://blitline.com/). New services: [rokka](https://rokka.io/en/) by Liip(!?) from Switzerland and [Sirv](https://sirv.com). ## Final words Commercial CDN services are doing a useful job. YOU the sophisticated web developer should be aware of this. ## Disclosure We have no business relation with any of the above mentioned providers. These are not affiliate links. Everything here is 100% opinionated and subject to changes and errors. # Market overview: Domain services for developers Source: https://blog.fortrabbit.com/market-overview-domain-providers Created: 2017-07-18 Author: Frank Lämmer Tags: webdev > An opinionated field guide on developer-friendly domain hosting services. ## Concepts ### Classical domain+hosting bundles Back in the dark days you have had all your hosting in one place: web-space, domains and even private e-mail hosting where bundled. This is still how most of the shared hosting works. And for many consumers (B2C), keeping all the website stuff in one place is actually quite a convenient solution. There is only one login, one technical support and one bill to pay — so that's totally OK for the restaurant owner and hir website. ### Decoupled is better Modern cloud hosting vendors (like us) are more specialized. Domain name services are mostly excluded. This makes your whole hosting setup a bit more complicated, but also more professional and it comes with following benefits: #### 1. No lock-in The usual domain registration period is one year (for some domains even two years). Bundled web packages (web-space + domain) can therefore only by canceled every other year. This can be really frustrating in case you'll ever get mad on your hosting provider — imagine unexpected downtimes, missing tech support or outdated software versions. With separated solutions for domain and web hosting, you can move your hosting more easily. Web hosting transfers are always a hustle. But if you've already registered the domain externally, you'll only need to update your DNS settings to point to the new host. #### 2. More professional As a web developer you are probably dealing with more than one domain. So you are looking for a professional DNS and domain registration service — more options, more freedom. ## Checklist Let this be your path through the jungle: ### 1. E-mail integration Before you dig too deep — consider your personal e-mails. This can be a deal-breaker. In many cases you may want to have e-mails with your domain, like: `hello@yourdomain.com`. Beware that not all specialized domain services offer this. Options here are: 1. **No e-mail necessary**: You may not need e-mails from that domain anyways. Applies to small projects or backends or some kind of web application. 2. **E-mail forwarding**: might do the trick. Someone writes to `hello@yourdomain.com`, you answer from your good old gMail. 3. **Integrated e-mail hosting**: Your domain provider also provides the e-mail accounts. Mostly old-school hosting providers have combined domain-email packages. 4. **External e-mail hosting**: When the domain belongs to a Company with are employees all in need to have IMAP e-mail accounts, you may look into a specialized e-mail hosting service like gSuite. (Future post planned) ### 2. (Location) For the web hosting part of your hosting you should care about the geo location of the actual servers. Those should be close to your visitors to reduce latency. For domains this is not so important. Of course it still matters where on earth the name servers (NS) are located, but those are not called that often as the results are heavily cached (TTL). So you can safely choose a domain provider from the other half of the world in terms of performance. As most providers offer a range of 100+ TLDs, your desired local country code will likely be included. ### 3. (Pricing) While researching for this article I found domain registrars are often compared by price. For me, that plays not a major role. The domain registrar costs are mostly relatively small compared to the hosting and other costs around your project. My tip: Don't consider pricing too much when only dealing with a handful of domains. Look locally, when country-specific TLDs matter to you. Don't get blinded by first year and special offers. Also look at transfer and renewal costs. Some providers offer bulk-rates. ### 5. Privacy Back in the days, your domain had to be registered on your name and your postal address. This information was (and is in theory still) public and can be accessed via whois. Try `whois fortrabbit.com` in your terminal to see WHOIS for our domain. Nowadays it's pretty standard to mask this. Look for WHOIS privacy protection. ### 8. SSL You want your domain to be reached under `https://`. Thanks to Let's Encrypt — TLS - it's actually no longer called SSL - is becoming a commodity. Some domain providers are (still) offering paid SSL certificates, some are making use of the Let's Encrypt service. Our clients do not need to care as we register LE certificates for all custom domains on our side automatically (zero-config). In most cases you can also use an external service for just this. ### 9. Look & feel I don't know about you. I trust well done interfaces more. 90ies looking websites and dashboards are suspicious to me. I don't like up-selling bullshit. I don't want my unused domains parked for ad-revenue, nor I want to make the provider to promote his services with my parked domains — this is what happens with some of the old-school providers. ### 10. Advanced features Geek out about useful features and eye-candy: 1. Domain registration directly from Slack (do you really need that?) 2. Domain registration right from the terminal via CLI 3. API to manage domains programmatically / webhooks 4. Bitcoin payment support 5. Domain market place ot buy and sell domains 6. Concierge service (human help) 7. Domain ALIAS support (for naked domain CNAME functionality) ## Candidates Domain registrars come in many different shapes and colors. Read: the service ranges differ. While one provider has the best possible DNS interface, the other have e-mail hosting built-in, while the third service just has the best pricing. The usual suspects: | Domain provider | .com / yr | info | | -------------------------------------------------- | --------: | :------------------------------------------------- | | [DNSsimple](https://dnsimple.com/) | $14.00 | Modern DNS with integrated domain registrar. | | [Gandi](https://www.gandi.net/domain) | €12.54 | Big shared hosting from FR, also domains | | [GoDaddy domains](https://uk.godaddy.com/domains/) | €15.99 | Huge shared hosting, with a bad rep, also domains. | | [Google domains](https://domains.google/) | $12.00 | Google also does domains, not availble in EU yet. | | [hover](https://www.hover.com/) | $14.99 | Specialzed in domain & e-mail hosting. | | [iwantmyname](https://iwantmyname.com/) | €11.90 | Straight forward popular domain only provider. | | [name.com](https://www.name.com/) | $12.99 | Shared hosting with focus on domains. | | [Namecheap](https://www.namecheap.com/) | €9.36 | Shared hosting with a focus on domains. | | [namesilo](https://www.namesilo.com/) | $8.99 | Looks cheap and a bit outdated. | | [OVH](https://www.ovh.ie/) | €9,99 | French hosting with domains. | | [Porkbun](https://porkbun.com/) | $8.84 | Oink. Designer focused domain hosting service. | | [Route 53 by AWS](https://aws.amazon.com/route53/) | $12.00 | Did you know? AWS also does domains. | And there are also: [1&1](https://www.1and1.com), [Directnic](https://directnic.com/), [Hexonet](https://www.hexonet.net/), [123 reg](https://www.123-reg.co.uk/), [Dotster](https://www.dotster.com/), [Moniker](https://www.moniker.com/), [Rebel](https://www.rebel.com/), [Network Solutions](https://www.networksolutions.com/) and many many more. ## Further readings ### Domains for clients Freelancing web designers need to decide whether they register domains on behalf of their clients or if that, together with hosting and the web design is something sold as a package for the client. This of course, depends on your and your clients level of professionalization. We advocate for a clean separation of concerns. Let the client own the web-hosting and the domains. For the web hosting, our service includes team features to transparently work on behalf of the client. I haven't seen this with domain registration yet. ### DNS & CDN services All domain providers are offering you DNS services. So you can use the name servers of the registrar. You can however also run your own name servers or book a specialized DNS service. Why even separate more? It brings even more features and freedom. DNS services are coming with better fail-over global DNS networks, HTTP/2 uplift, anycast and other features. They also blend into Content Delivery Networks. Here is a small list: - [DNS made easy](https://dnsmadeeasy.com) - enterprise DNS provider - [Cloudflare](https://www.cloudflare.com/) - CDN, domain security & DNS - [PointDNS](https://pointhq.com) - DNS as a service - [Section.io](https://www.section.io/) - CDN grid - [Greta](https://greta.io/) - P2P decentralized CDN (cool kids) - [keycdn](https://www.keycdn.com/) - modern Content Delivery Network But that's a topic of it's own which might be reflected in a future post. ## Disclosure We have no business relation with any of the above mentioned providers. These are not affiliate links. Everything here is 100% opinionated and subject to errors. # Market overview: Email services for business and private Source: https://blog.fortrabbit.com/market-overview-email-as-a-service Created: 2017-10-30 Author: Frank Lämmer Tags: webdev > An opinionated field guide to email hosting providers, for teams whose PHP host deliberately does not run their mailboxes. We do "PHP as a Service" here, specialized in PHP website/application hosting — **no frills attached**. So we expect our clients to have their e-mail hosted elsewhere. There are two types of e-mails you'll need to take care of: 1. **Transactional emails**: Automated, triggered _← see [prev post](/market-overview-transactional-mails)_ 2. **Email accounts**: for your domain _← this post_ ## Options This is a support-driven post — based on my experience with our clients. It's a guideline for anyone considering options for e-mail hosting and stand-alone email hosting solutions in detail. This is aimed for small business owners and developers of course. So this is what you can do about your email accounts in general: ### 1. No domain-attached email at all It's totally normal to have a business email with a gmail.com suffix these days. So you might just create a generic Gmail account for your service as well, like: _myservice@gmail.com_. OK: it's a bit of hack, but why not get you started for free? Few of our clients are actually doing this. ### 2. Run your own You might be tempted to spin up a mail server (MUA, MTA, MDA) on your cheap VPS. Just don't do it, you will drown in SPAM. ### 3. Classical hosting bundle You might still have a classical web-hosting running somewhere. Those packages often include domain registration and e-mail services. So why not use this, when included anyways? Some classical hosting providers are also offering e-mail only packages. Many of our clients are still doing this. Is this you? Read on to learn about alternatives. ### 4. Dedicated email service Now, this finally gets interesting. A dedicated email service might bring you benefits you are not aware of yet: ## Features > Who needs email these days anyway? E-mail was considered dead many times (remember Google Wave?). Still, more and more communication goes away from e-mail to services like Slack, WhatsApp, Telegram and alike. Each dedicated email service offering will include additional features. Some kind of office (at least Calendar and Contacts) integration is common, but also team management, fancy clients, backups and security. ## To be considered ### Privacy and security In Germany all business correspondence needs to be kept for 10 years. This also includes your e-mails. How do you make sure that you'll not loose the data? Can you trust your cloud provider? Does the sexy looking US venture comply with your privacy and tax local laws? ### Pricing Dedicated Email as a Services are more expensive then packaged goods. One usually pays per seat (aka mailbox), usually something around 5 €/$ monthly. The bigger the team, the higher the costs. ### Geo location Hosting used to be local business, but in fact it doesn't matter too much where your mail-servers are geographical located from a service level point of view — email is not real time communication. But maybe the location does play a role in terms of privacy or maybe you just want the GUI to be displayed in your local language (Hello Europe!). ### Client #### Classical mail clients Your OS has a mail client of course and all the different solutions here are compatible with standard postboxes (IMAP, POP3 & SMTP). There is Outlook, Thunderbird and Apple Mail for desktop systems and simple "Mail" for mobile. #### Webmail But within increasing capability webmail clients (e-mail in your browser) are getting more popular as well. gSuite from Google issue popular for bringing stuff you already use and love to your business. Depending on your use case, the webmail user experience might play a role here is well. [SquirellMail](https://squirrelmail.org/) for example is a great piece of software, but it looks a bit dusty now. [Roundcube](https://roundcube.net/) first released 8 years ago, also great, is more modern and still actively maintained. Dedicated mail providers might have their own proprietary mail clients. ## Some private/business email providers Sorry — as usual, the market overview part of this market overview post is small. Do the research on your own — it's about your custom business needs. Take this as a starting point: | Provider | Type | focus | | ---------------------------------------- | --------- | ---------------------------------------- | | [ProtonMail](https://protonmail.com/) | dedicated | Secure mail from Switzerland | | [gSuite](https://gsuite.google.com) | dedicated | Full fledged office suite w Gmail for your domain | | [Namecheap Email](https://www.namecheap.com/hosting/email.aspx) | bundled | Email offering from domain provider | | [FastMail](https://www.fastmail.com/) | dedicated | Original email as a service | | [Zoho mail](https://www.zoho.com/mail/) | dedicated | Office solution with free entry | | [AWS workmail](https://aws.amazon.com/workmail/) | dedicated | Amazon swallowing everything | | [runbox](https://runbox.com/) | dedicated | Secure mail from Norway | ## Further readings ### Technical implementation Using an external e-mail service is actually quite simple to set up. Just configure your domain accordingly, by pointing the MX (DNS) records to the service of your choice. ### Disclosure We have no business relation with any of the above mentioned providers. These are not affiliate links. Everything here is 100% opinionated and subject to changes and errors. # Transactional e-mails market overview Source: https://blog.fortrabbit.com/market-overview-transactional-mails Created: 2017-09-21 Author: Frank Lämmer Tags: opinion > What transactional email services are for — confirmations, invoices, password resets — and which providers are worth a look. ## About transactional e-mails Your web application needs to send personalized, triggered e-mails. For example: 1. double-opt in e-mail to confirm an Account 2. an e-mail with the monthly invoice 3. an e-mail to reset a password to login to your service again So, this is not a newsletter where one person is sending out the same mail to a bulk of receivers, this is where a bot sends personalzied mails one by one. > PLUG: Please also see our article on [how we do transactional e-mail](/how-we-do-transactional-mail) to learn some practices on sending those e-mails. ## The problem Back in the days you might have just used the [PHP mail function](http://php.net/manual/en/function.mail.php) like so: ```php $to = 'firstname.lastname@gmail.com'; $subject = 'Welcome to awesome service'; $message = 'hello, nice to have you here …'; $headers = 'From: webmaster@mycoolapp.com' mail($to, $subject, $message, $headers); ``` The issue with this is: that mails are sent anonymously — not from a real mail server, just from from a script. So your e-mail is highly suspicious — it smells like SPAM — and thus is not likely to ever reach the Inbox of your clients. That's why you might not do this any more. Sendmail is disabled with our hosting service here for this reason. ## The code level solution Use a script/package that is sending the e-mail over a real mailserver. So your script behaves the same as your local mail client: It uses SMTP to authenticate with username and password. This way the sender of the e-mail (your app) can be verified by the receiver (your client) and — and thus the mails are much more likely to reach inboxes. You can easily plug in one of these PHP packages (via Composer): * **[Swiftmailer](https://swiftmailer.symfony.com/)** < recommended * [PHPMailer](https://github.com/PHPMailer/PHPMailer) ## The other side of the problem Well, now that you are using the correct script, you'll need access to a mailserver. Your options here are: ### Using Gmail So you might just create a Gmail account for your App, like `myapp@gmail.com`. Then you'll need to [enable access for less secure Apps](https://support.google.com/accounts/answer/6010255?hl=en) within the Gmail Dashbaord and you can use it like that. But hold on: Your clients are expecting that your App which lives under `yourappdomain.com` will send emails from `yourapp@gmail.com` -> That gmail address will not look trustworthy to your clients as a sender. ### Using gSuite You can also have all the Gmail-goodness with your own domain with gSuite (aka Google Apps for Business). It is possible to use gSuite as a SMTP relay to send bulk mails, but probably not recommended. gSuite is about e-mail accounts for personal usage, there are limits. ### Install your own Already running on a VPS? Well, congrats, you have root access. So you can install anything, this includes your own MTA (Mail Transfer Agent), probably Postfix. Please be prepared for this to be a bit complex and also mind that it comes with security risks and you'll need to maintain it — imagine someone hacking your mail-server to send SPAM. ### Use a commercial provider You already see some pain points? Commercial offerings are the solution. Transactional mail service providers are specialized on that very topic. Beside an SMTP interface you'll get: an easy to use restful API, instant delivery, help with setting up your DKIM and SPF records for your domain, e-mail templates, logging, statistics, bounce alerts, click tracking, inbound e-mails and much more. Some providers are also in the space between marketing and automated informational e-mails. ## The providers Here are some commercial services for transactional e-mails. Sorry, I can't tell you which is the best one — haven't got the time to test them all: Well known are: [Amazon SES](https://aws.amazon.com/ses/), [Mailgun](https://www.mailgun.com/), [Mailjet](https://www.mailjet.com/), [Postmark](https://postmarkapp.com/), [SendGrid](https://sendgrid.com/), [SendInBlue](https://www.sendinblue.com/). Not so well known but also available: [Doppler Relay](https://www.dopplerrelay.com/en), [Dyn email](https://dyn.com/email/), [GrennArrow](https://www.drh.net/), [Pepipost](https://pepipost.com/), [Socketlabs](https://www.socketlabs.com/), [Sparkpost](https://www.sparkpost.com/). Special mention goes top [mailtrap](https://mailtrap.io/) which is a service dedicated to bring you safe e-mail testing with a fake SMTP server to test and view the mails your application is sending. Sorry, the market overview part is slim, but at least you hopefully know now why to use a transactional mail provider. You'll probably can find your own favorite. ## Disclosure We are using Postmarkapp ourselves but beside that we have no other business relation to any of the services mentioned here. No affiliate links. cheers # Market overview: video hosting for business Source: https://blog.fortrabbit.com/market-overview-video-hosting Created: 2017-08-14 Author: Frank Lämmer Tags: webdev > An opinionated field guide to video encoding and hosting services, and when outsourcing video beats serving it from the web server. ## Why and when to outsource video encoding & hosting So, you want to play some video on your website. Why not? Video is great for marketing. Video can also often explain things better than a thousand words. Your users bandwidth is growing. Video encoding algorithms are getting better. Flash is officially dying. HTML5 video is here to stay. You might just embed a video or two on your landing page. But what if you have a lot of videos to show? Or what if you want your client to upload videos any kind of video to be encoded? Consider: ### 1. video files are large Even highly compressed and web-optimized - video files eat up a lot of disk space. With a web hosting service like fortrabbit, the storage is limited, so keep an eye on that. ### 2. video streaming costs a lot of traffic It needs a lot of bandwidth to stream video. Keep an eye on the included traffic limited with your web-hosting. ### 3. video encoding is hard to do right Creating small but good looking videos that are supported on all devices is actually more complicated than it might seems first. [ffmpeg](https://www.ffmpeg.org/) — as you hopefully know — is a great piece software. It's the swiss army knife for video encoding. It's free and open source. And it is well documented. But there is a lot to master about video codecs and options. [Here](https://gist.github.com/Vestride/278e13915894821e1d6f) is a good starting point on encoding video for web (mostly macOs). ### 4. video encoding eats your CPU Have you ever watched your CPU running hot when crunching videos? That's the reason why ffmpeg is not installed on fortrabbit. We believe in light containers - specialized for web delivery. Visitors should not have to wait, while a video is being encoded. ## Commercial video encoding & hosting services You see? Outsourcing your web video to a professional service might be good idea. There are various options to match your needs: ### YouTube and Vimeo This is — of course — a very common choice. When your videos are meant for public domain and you even want leverage an additional channel (platform): **YouTube** is not only great for cat videos, it's also good for hosting your business videos. The encoding is super fast. It has an integrated CDN. The player is bullet-proof. You can easily implement YouTube videos with an iFrame. There are a ton for plug-ins for each CMS. Plus: It's totally free of costs. But: The YouTube player is branded, and maybe that looks a bit cheap to your eyes? YouTube might even run commercials around your embedded video some day. **Vimeo** on the other side has (paid) [video for business](https://vimeo.com/business) - offering more control and a more white-label-like experience for the end-user. So these are already very good choices to start with. ### Vanity business video hosting Similar, yet even more professional are: [Wisita](https://wistia.com/), [Sproutvideo](https://sproutvideo.com/), [vidyard](https://www.vidyard.com/), [vzaar](https://vzaar.com) and [TwentyThree](https://www.twentythree.net/) — all with different features and focus. Marketers will get analytic insights on video plays and drop off rates and also integrations with third party services like CRM. A bit more in the enterprise section here are [encoding.com](https://www.encoding.com/) and [brightcove](https://www.brightcove.com/en/) offering end-to-end media solutions (what ever that means). ### Just encoding Special mention goes to [coconut](http://coconut.co/) which is developer focused and is just doing the actual video encoding. So this work great, if you have already have a (push) CDN (see our [post](/market-overview-cdn)) to host your videos. ## Final words Commercial video encoding services are doing a useful job. YOU the sophisticated web developer should be aware of this. ## Disclosure We have no business relation with any of the above mentioned providers. These are not affiliate links. Everything here is 100% opinionated and subject to changes and errors. # Mastering HTTP Caching Source: https://blog.fortrabbit.com/mastering-http-caching Created: 2017-02-24 Author: Ulrich Kautz Tags: webdev > Which HTTP response headers a CDN edge cache actually reads, how they interact, and how to use them without breaking a dynamic site. To use **C**ontent **D**elivery **N**etworks as HTTP caches you need to know about the proper HTTP response headers: Which are relevant? How do they work? How to you use them? All this I try to answer in this article. The post does not claim to be exhaustive or even completely precise. In some instances, I will simplify and be opinionated for the sake of clarity, brevity and reduced complexity. This text handles the theory of caching - with a couple of practical examples, though. There will be follow up articles, building on this one, showing how to work with a CDN as caching layer with specific CMS or frameworks. ## Why use a CDN? CDNs are intended as a globally distributed network to provide (not only) website contents faster to geographic locations, which are far from the actual infrastructure, which serves the actual content. For example: Your website is hosted in Ireland, your clients mostly sit in Australia. When a client visits your website the connection will suffer from latency leaving you with a sad client. Moving the (static) data to Australia with a CDN improves the client's experience. However, CDNs are not limited to this use-case. As per their nature, CDNs are also a plain and simple cache; a **proxy cache** (or edge cache) to be precise. So, even if the geographic location part is non of your concern, you still should consider using the proxy cache aspect of CDNs to improve the experience of your users. ## Why use a Proxy Cache? In short: Proxy caches take load of your web server and, since they are delivering only "static" content, are much faster. A simple example: Say you have a blog with a start page, listing all recent blog entries. To do that, a PHP script loads the latest blog entries from the database and renders them into an HTML result page. So for one request/visit: One PHP execution + a couple database queries. For a thousand requests/visits: a thousand PHP executions + a couple thousand database queries. Every PHP execution requires CPU, memory and I/O. Same goes for every database query. The resource requirements scale linear with the amount of requests/visitors. Sounds good? It's not, because it will only scale linear up to a point: Any disk can only deliver so much I/O. Neither CPU nor memory are infinite. At some point, one of those bottlenecks will become critical and however much of the other resources you have won't matter: The website will become very slow, maybe even not responsive at all anymore. Sure, you can scale out horizontally, but that would make things a lot more complex, a lot more expensive and there is a much cheaper and far less complex solution: A proxy cache in between allows you to mitigate resource limitations. Using the above example, with a proxy cache, only the first request would need to execute the PHP script, do the database queries and render the result HTML. All subsequent requests would be served from the cache. Cache access is basically direct memory access, which is about as fast as it gets. This means: the linear scaling problem is no more! A hundred visitors or a thousand visitors, it doesn't matter. Still only one PHP execution, one time database queries, one time rendering. ## CDN != CDN There are various "kinds" of CDNs out there. Administrators would probably be most interested in where and how the data is stored and how the data is distributed within the CDN and differentiate by that. Since this is article is not addressed to administrators but developers let me just say that there are "classic CDNs" and "peer to peer CDNs", the latter being the modern approach. From the developer perspective, it's more interesting how you get data into the CDN rather then how it then handles said data. In that sense, there are **push CDNs** and **pull CDNs** (also called "origin pull CDNs"). As their name implies, the push CDNs expect you to provide them the content while pull CDNs take care of fetching the content themselves. This article will primarily address pull CDNs, because they are much simpler to implement and can, in many cases, be integrated transparently before an existing website without much effort. ## How pull CDNs work Let's try an example and say you have a website, which is available under the URL `https://www.foobar.tld` to your visitors. In this scenario, the domain `www.foobar.tld` would be routed to the pull CDN server, not your web server. The CDN acts as **proxy** for the web server. Another domain, which won't be publicly known, would route to the actual web server. Let's name it `direct.foobar.tld` for this example. The web server is called the **origin**. The CDN now accepts any incoming request and either answers it directly from it's cache or delegates it to your web server, caches the response for future requests, and then delivers it to the client. ``` +-------+ | | | Cache | [origin] | | direct.foobar.tld +-^---+-+ | | | v +--------+ +-+---v-+ +------------+ | +-------> +----------------------------------> | | Client | | CDN | | Web Server | | <-------+ <----------------------------------+ | +--------+ +-------+ +------------+ ^ | www.foobar.tld [proxy] ``` The most simplistic pull CDN would act as following: - Get a request to `http://www.foobar.tld/some/page` - Take `some/page` as cache key and check if it's already in the cache - In cache: deliver result from cache - Not in cache: request `http://direct.foobar.tld/some/page`, write response under `some/page` in cache and deliver ## Static vs dynamic content The above setup works fine for completely static contents. Static contents means: Any data, which does not change for all visitors requesting the same URL. A good example would be assets, like CSS files. Say `http://www.foobar.tld/public/css/main.css`, where `main.css` is actually a plain file, which is the same for anybody visiting the site. Perfect for caching. Opposed to static contents are, of course, dynamic contents. There are various reasons as to why content must be generated at runtime. Think, for example, about multi-language: Deliver contents based on the browser language. Also any kind of "user session" related content, such as switching the "Login" button with a "Logout" button when the user is logged in. You don't want that cached. Also don't forget about highly active contents as well: News pages, which change hourly or even more often, cannot be cached - or at least not for long. Don't panic now. This is where it gets interesting, but still not hard to understand or implement: ## Cache headers Most, if not all, pull CDNs allow you to address the issue of dynamic contents by allowing you to control the cache behavior "per page", or to even higher degrees (more on that later). To that effect, the simplest solution are good ol' HTTP response cache headers. The first thing you should know about cache headers is that there are "old ones" and "new ones". Meaning: It was a process, not planed. New, in this case, means introduced with HTTP/1.1, while the old ones were specified with HTTP/1.0. Either way, the amount of available options lead to a lot of confusion about the whole topic and is in my opinion the single largest reason why people shy away from using cache headers. To make it simple, let's concentrate on `Cache-Control` and `ETag`. Both are sufficient. Most CDNs still accept the "old ones" (`Expires`, `Pragma` and `Age`), but they are mostly used as a fallback, i.e. if you don't use the "new ones", then the "old ones" will be accepted. ### ETag header Let's start with an easy one: `ETag`. It identifies the version of the document. Usually that means an MD5 hash over the content, but it could contain any value, representing the version/state of a document. Eg `1.0` or `2017-02-22`. One thing of note: The value must be double quoted, for example: `ETag: "d3b07384d113edec49eaa6238ad5ff00"`. ### Revalidation Now to the practical application of `ETag`: revalidation. Let's forget the whole proxy + origin setup for a moment and just consider a simple client <-> server setup, to make this easy. Here is the setup: ``` +--------+ +------------+ | +-------> | | Client | | Web Server | | <-------+ | +--------+ +------------+ ^ | www.foobar.tld ``` Now, let's further assume the client is making a request to `http://www.foobar.tld/hello.txt`. The server then serves the content with the following response: ``` # REQUEST GET /hello.txt HTTP/1.1 Host: www.foobar.tld # RESPONSE HTTP/1.1 200 OK Date: Sun, 05 Feb 2017 12:34:56 UTC Server: Apache Last-Modified: Sun, 05 Feb 2017 10:34:56 UTC ETag: "8a75d48aaf3e72648a4e3747b713d730" Content-Length: 8 Content-Type: text/plain; charset=UTF-8 the body ``` There are two interesting headers in response: Of course `ETag`, with the MD5 over the content and also `Last-Modified`, with a date of the last modification of `hello.txt`. Now here is how revalidation works: When the client visits the URL again within a short time, the client's browser use one of those `If-*` request header, for example: `If-None-Match`, which checks against the content of `ETag`. This request header makes clear, that the client would accept either a full response or a response indicating that the content was not changed. ``` GET /hello.txt HTTP/1.1 If-None-Match: "8a75d48aaf3e72648a4e3747b713d730" Host: www.foobar.tld ``` Now, if the `ETag` has _not_ changed, then the server could respond with: ``` HTTP/1.1 304 Not Modified Date: Sun, 05 Feb 2017 12:34:57 UTC Server: Apache Last-Modified: Sun, 05 Feb 2017 10:34:56 UTC ETag: "8a75d48aaf3e72648a4e3747b713d730" Content-Length: 8 Content-Type: text/plain; charset=UTF-8 ``` As you can see, this time the server response was not a _200 OK_, but a _304 Not Modified_, which omits the body and leads the client to use what was cached before. Sure, in case the body is only _the body_, as in this example, there is not much gained. But think of larger contents. Also think of expensive, dynamically generated contents. As a developer, you might now think: _Not so great. Means that I have to handle those `If-` header in my application myself. More effort then before._ No worries. This is where the shared cache aka proxy aka CDN comes in. So going back to the original setup (client <-> proxy <-> origin). The proxy now is responsible for generating those _304 Not modified_ responses, based on it's cache. More on that in the following section. Before I get to it, a quick note on the `Last-Modified` header: In this particular case, dealing with static content, which the `hello.txt` file is, the client could also have used `If-Not-Modified-Since: Sun, 05 Feb 2017 10:34:56 UTC` to achieve the same result (304 response). This works great with static contents, since the `Last-Modified` header in responses to static contents is automatically generated by the web server based on the modified timestamp of the file on the disk. However a modified date is often useless, because hard to determine, for dynamically generated contents. You know, the contents you want to have cached the most, because they are the most expensive to generate. So when developing, the `ETag` header is often a better choice. ### Cache-Control header The `Cache-Control` header is a bit harder. It's harder for two reasons: first, `Cache-Control` can be used as request **or** response header. In this article, we only care about the response part, because this is what the developer has control of. Secondly, it controls potentially **two cache locations**: The "local cache" (aka "private cache") and the "shared cache". The **local cache**, is a cache on the local disk of the machine running the browser. Your laptop, if you will. Be aware that you don't have "exact control" over that cache. Ultimately, the browser decides whether to follow your "suggestions" or not, which means: don't rely on it. The user might as well clear all caches whenever the browser is closed and you would not know about it, aside from increased traffic cause those caches invalidate faster then you anticipate. The **shared cache**, is what this article is about: A cache in between the web server and the client. The CDN, in this case. You have full control over the shared cache and should leverage it to the fullest. Hence this article. OK, let's dive in with some code examples. I'll explain in detail below: 1. `Cache-Control: public max-age=3600` 2. `Cache-Control: private immutable` 3. `Cache-Control: no-cache` 4. `Cache-Control: public max-age=3600 s-maxage=7200` 5. `Cache-Control: public max-age=3600 proxy-revalidate` That might look a bit confusing, but don't worry, it's not that hard. First you should now that `Cache-Control` takes three "kinds" of directives: Cachability, expiration and revalidation. First **cachability**, which takes care of the cache location, which in includes whether it should be cached at all. The most important directives are: - `private`: Means it shall only be cached in the local (private) cache. On your laptop. - `public`: Means it shall be cached in the shared cache. In the CDN. It can _also_ be cached on the local cache, though. - `no-cache`: Interestingly this means caching is allowed - just everybody (local cache, shared cache) must revalidate before using the cached value - `no-store`: Means it shall not be cached. Nowhere. Not ever. Next up is **expiration**, which, obviously, takes care of how long things are cached. The most important directives are: - `max-age=`: Sets the cache validity time. How many seconds shall the cache location keep it? Goes for local _and_ shared cache. - `s-maxage=`: Overrides `max-age` just for the shared cache. No effect on local cache. Lastly there is **revalidation**, which is, more or less, fine control. The most important directives are: - `immutable`: Means that the document won't change. Ever. Can be cached until the heat death of the universe. - `must-revalidate`: Means the client (browser) must still check with the proxy (CDN), even while it's cached! - `proxy-revalidate`: Means that the shared cache (CDN) must check the origin, even while it's cached! And to put it all together, here is how to read the above code examples in plain English: 1. Cache it both on CDN and laptop for an hour. 2. Don't store in CDN, only on laptop. Once cached (on laptop), no need to ever refresh it. 3. Don't cache it - or do. Just make sure to revalidate always! 4. Cache it for an hour on laptop, but for two hours on the CDN 5. Cache it both on CDN and laptop for an hour. BUT: if a request hits the CDN, although it's cached here for an hour, it still must check with the origin whether the document is still unchanged. ### Example To break the monotony of theory, a short practical example on how to auto-inject `ETag` and `Cache-Control` headers. The example is meant for an Apache `.htaccess` file, but I hope you get the gist and are able to apply it to your web server of choice accordingly. ``` # Set ETag and cache for one day for all images: FileETag -INode MTime Size Header set Cache-Control "max-age=86400 public" # Set ETag and cache for two hours, but assure revalidation, for all CSS, JS assets FileETag -INode MTime Size Header set Cache-Control "max-age=7200 public must-revalidate" Header unset Last-Modified ``` Given the above, a response for the URL `http://www.foobar.tld/baz.jpg` would contain an `ETag` header, built from the modification time and size of the file, and a `Cache-Control` header with one day cache lifetime. ``` # REQUEST GET /baz.jpg HTTP/1.1 Host: www.foobar.tld # RESPONSE HTTP/1.1 200 OK Date: Tue, 07 Feb 2017 15:01:20 GMT Last-Modified: Tue, 07 Feb 2017 15:01:15 GMT ETag: "4-547f20501b9e9" Content-Length: 123 Cache-Control: max-age=86400 public Content-Type: image/jpeg ``` A response for the URL `http://www.foobar.tld/dist/css/styles.css` would also contain an `ETag`, based on modification time and size of the file, as well as a `Cache-Control` header with two hours cache time. Also the `Last-Modfied` header would be stripped, to assure that only `ETag` is used for revalidation. ``` # REQUEST GET /styles.css HTTP/1.1 Host: www.foobar.tld # RESPONSE HTTP/1.1 200 OK Date: Tue, 07 Feb 2017 15:00:00 GMT Server: Apache ETag: "20-547f1fbe02409" Content-Length: 32 Cache-Control: max-age=7200 public must-revalidate Content-Type: text/css ``` ## Cookies Now that you understand how caching headers work, let us consider how cookies play into caching. Firstly, Cookies are HTTP response headers. Namely the `Set-Cookie` header. The purpose of providing a cookie to a user is to identify the user, hence you _need_ a unique cookie per user. When putting that in context of caching: Would you cache the response, including the `Set-Cookie` header, then every user (during cache time) would get the same cookie and thereby the same user session. [You don't want that](https://www.owasp.org/index.php/Session_hijacking_attack). The other implication is that the user session state potentially changes the rendered content of the response. Simple scenario: Eshop basket. Based on the session cookie your application either renders no basket or renders a basket with the items this specific user has chosen. Again: You don't want that cached. Each customer should have their own basket, after all. Having this said, don't confuse these session cookies with the more "benevolent" kind. A good example for the latter are Cookies set at runtime, via JavaScript. For example: Google Analytics integrated via JavaScript. GA sets a cookie (via JS), but this cookie does not impact rendering nor is there any `Set-Cookie` header involved. Even if GA would change the rendered site, eg by adding a small "you are tracked via Google Analytics"-icon, or something, it would not be a problem _as long as those changes are applied at runtime, in the browser and not by the (PHP) script in the background_. ### Dealing with cookies vs caching First thing you should become aware of is how your web application (the underlying CMS/framework) works with cookies. Are cookies used sparsely, eg only during the login process? Are cookies injected into any response, on principle? Do you have control over when cookies are set? To emphasize the previous section: Whenever you serve a response, which contains a `Set-Cookie` header, you want to make sure it is not cached. The same goes, when you render response, which contains "user specific" contents (eg the basket, from before). What this means depends on how CDN/proxy acts. For example: - Does it support a default or fallback caching time, which is used to inject a `Cache-Control` header, if non is provided? - Does it automatically strip any `Cache-Control` header, if `Set-Cookie` is present? Once you know how your web application acts, regarding cookies, and what your CDN does, in terms of automagic, you can go about implementing your own defaults and preferences. Following an Apache `.htaccess` file example, which will help you getting started: ``` # 1) Enable caching, if COOKIE IS NOT used Header set Cache-Control "public max-age=3600" "expr=-z resp('Set-Cookie') # 2) Disable caching, if COOKIE IS used Header always remove Cache-Control "expr=-n resp('Set-Cookie') # 2a) Alternative to above: set caching to 0, if COOKIE IS used Header set Cache-Control "no-cache max-age=0 must-revalidate" "expr=-n resp('Set-Cookie') ``` - Rule (1) sets the `Cache-Control` header with a default value, _if no Set-Cookie header exists_ - Rule (2) does the opposite: Strip `Cache-Control`, _if the Set-Cookie header does exist_ - Rule (2a) is a variant of the second, which sets an explicit 0-cache, instead of stripping the cache header. #### Path based cookie suppression Some CMS/frameworks seem to follow a brute-force'ish strategy, saturating generated responses automagically with an abundance of `Set-Cookie` headers. Whether setting those cookies with each and every response is necessary or redundant depends on various factors. For example session time: If you have a high security application with a very low session time of 5 minutes, then setting a new cookie with every response makes sense. If you not even have a "user space", i.e. everything is public and the same for every visitor, then setting any cookie (aside from tacking purposes) makes no sense. So whether you can use the below example or not, depends strongly on your application. Either way, here we go. To give this example some context: Let's say you have a news website. All news posted news items are withunder `http://www.foobar.tld/news/item/`. Now you want to make sure that all responses to those `/news/item/` paths do not contain a `Set-Cookie` header, _because you made sure that those cookies are redundant_: ``` # the usual PHP redirect .. note the `?path=$1` in the rewrite rule RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA] RewriteRule ^$ index.php [NC,L,QSA] # using the previously set `path=` from the query Header always unset Set-Cookie ``` For those who are interested: The redirect, using `path=$1` and the subsequent evaluation of `QUERY_STRING` are necessary in Apache, due to the execution order of the Apache directives. `If` is simply later evaluated then `RewriteRule`, so it cannot use the `REQUEST_URI` or anything of the original request, because that has already been changed due to the rewrite. #### Cachability by design There are design strategies to assure a web application is highly cachable. Since this is an article, and not a book, I cannot go into all, but let me highlight one commonly used for you: Let's use the eshop example once more. Say there is a home page, which lists the top items for sale or something like that. Those top items are expensive to generate (lots of database queries), so you want them to be cached. The problem is the basket, from before, which should be rendered for logged-in users, but not for users which are not. ``` +----------------------------------+ | Welcome +-----------+ | | | 3 items | | | * Item 1 for $5 | in basket | | | * Item 2 for $10 +-----------+ | | * Item 3 for $7 | | | +----------------------------------+ ``` The strategy would now be to first render the "generic" page, which every user, independent of the login state, sees. Then you load the unique basket via JavaScript and render it into the existing page. From the user's perspective, it looks the same eventually. Granted, instead of one request (render whole page, including basket) you now have two requests (render whole page + render basket). Still, you omit the "expensive" part, those top sales items, since that part is cached. ``` +----------------------------------+ +----------------------------------+ | Welcome +-----------+ | | Welcome +-----------+ | | | place | | | | 3 items | | | * Item 1 for $5 | holder | | ==[JavaScript]==> | * Item 1 for $5 | in basket | | | * Item 2 for $10 +-----------+ | | * Item 2 for $10 +-----------+ | | * Item 3 for $7 | | * Item 3 for $7 | | | | | +----------------------------------+ +----------------------------------+ [generic page] [decorated with user] ``` This strategy, or variations thereof, is hard to apply to existing applications, cause it would change most of it's controller and probably most of the view layer (given a MVC layout). Best you make sure to do it from the start. ## Cache invalidation: Busting and purging With the `max-age` and `s-maxage` directives, you already have detailed control on how long a specific response is to be cached. However, that's not sufficient in all cases. Those directives are set at rendering time. At this time, you simply might not know when the response should expire. Think for example about the home page a news website: Say, it contains the latest 10 entries. You set `max-age=900` for this home page, to make sure that is refreshed every 15 minutes. Now, one of the entries was published too early and shall go back to the drawing board again. You need a way to remove the cached response, so that it is refreshed now, not in 15 minutes. Don't worry, that's a common problem and there are tools to solve it. Let's first clarify the terminology: - **Cache busting** means to circumvent the cache, by changing the cache key. Remember the (very) above example of `http://www.foobar.tld/some/page`, for which `some/page` would be used as the cache key? When changing the request to `http://www.foobar.tld/some/page?v2` the key changes to `some/page?v2`. Cache busted. - **Cache purging** means to remove an item (aka a response) from the cache, so that it can/will/must be refreshed immediately. ### Cache busting with versioning This strategy is very often used with assets (eg CSS, JS, ..). The idea is to include your assets using a version scheme. Those can be actual versions, a hash of the content, a timestamp and so on. To give you a few examples: - Numeric versions: `style-v1.css`, `style.css?v=1` - Hash as version: `style.css?d3b07384d113edec49eaa6238ad5ff00` - Timestamp as version: `styles.css?t=1486398121` What you need to consider is the context. In this case: the rendered HTML, which includes the CSS file via ``, might be cached itself. So if your `style.css` is decorated with the latest version, it helps only if the CSS file is included using this latest version. If the HTML, which includes the CSS file, is served from the cache, it contains most likely the old version/file, so the old styles will still be served. ### Cache purging How to purge one or multiple items from a CDN depends on the individual provider. Since many CDNs are built upon the open source software [Varnish](https://varnish-cache.org/), a common strategy is to use the `PURGE` verb in an HTTP request, for example: ``` PURGE /news/item/i-am-obsolete HTTP/1.1 Host: www.foobar.tld ``` Those purge requests usually require some kind of authentication or at least a source check (i.e. IP whitelist), but that depends on the provider. While purging a single item, or a couple, is easy and fast there are scenarios in which that is not sufficient - or at least not elegant. For example, imagine a blog, which contains the author on most rendered pages. Now you change something in that "author block" and want to purge all "affected" pages. Sure, you can do that one-by-one, but if you have to purge a couple of thousand pages (ok, now leaving the blog example), then it can become harder. The solution for that problem are: #### Surrogate keys (aka Cache tags) The name "surrogate keys" is used by the CDN provider [Fastly](https://www.fastly.com/) and I like it best, so I will go with that in this article. Other providers call them differently. For example "cache tags" is a popular choice. Varnish calls them [Hashtwo/Xkey](http://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html#hashtwo-xkey-varnish-software-implementation-of-surrogate-keys), which is to cumbersome for me to use it here. However named, they serve the same purpose: Tagging responses with custom keys, so that you can purge them easily by those named tags, without even known what exactly has been cached. To give you a quick example, using the client <-> proxy <-> origin layout, here is what your origin would respond with when using surrogate keys: ``` HTTP/1.1 200 OK Content-Type: text/html Content-Length: 123 Surrogate-Key: top-10 company-acme category-foodstuff ``` In this example, the response is "tagged" with three surrogate keys: `top-10`, `company-acme` and `category-foodstuff`. To give that some context, with the eshop example: This response contains the top 10 items of the shop, the product rendered in this response is from the company ACME and the category this product is in is foodstuff. Having tagged the response, you can now easily purge all items in the cache which are tagged with `company-acme` or `top-10` or whichever custom context they are in. Easy, right? How the actual purging is handled, again depends on the specific CDN vendor. ## Finish That's about if for the theory. There will be follow up articles using specific CDN providers with specific CMS/frameworks. How many - we'll see. If you want to dig in now, here are some additional resources which you might want to read: - [Google Developers: HTTP Caching](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en#cache-control) - [Push vs Pull CDN](http://www.whoishostingthis.com/blog/2010/06/30/cdns-push-vs-pull/) - [CDN Types (admin perspective)](http://www.the-toffee-project.org/index.php?page=32-cdn-content-delivery-networks-types) - [Cache headers overview (KeyCDN)](https://www.keycdn.com/support/http-caching-headers/) - [Caching explained (Mozilla)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching) - [ETag header in detail (Mozilla)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) - [Cache-Control header in detail (Mozilla)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) - [If-None-Match header in detail (Mozilla)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) - [Fastly: Surrogate keys](https://docs.fastly.com/guides/purging/getting-started-with-surrogate-keys) - [KeyCDN: Cache tags](https://www.keycdn.com/support/purge-cdn-cache/) - [KeyCDN: Cache headers](https://www.keycdn.com/blog/http-cache-headers/) ## Bonus Learn how to [speed up APIs with HTTP Response Caching](https://blog.apisyouwonthate.com/speeding-up-apis-apps-smart-toasters-with-http-response-caching-a67becf829c6) - the API client and your server will be grateful. # MCP, CLI and API are here Source: https://blog.fortrabbit.com/mcp-cli-and-api-launched Created: 2026-09-02 Author: Frank Lämmer Tags: chronicles > Three three-letter acronyms for the new platform — and a skills update that glues them together. ## Fuzzy as a feature I don't know about you. I am excited and also very concerned about LLMs. It for sure has profound impact on our guild. Let's focus on the good parts now. I like how I can use vague, fuzzy input with only implicit instructions, still getting to concrete results. Now, we are releasing better interfaces for your agents to connect to our platform and work with fortrabbit domain knowledge. ## Simplistic demo ```raw > I want this deployed to fortrabbit! This is a Craft CMS project. I can create a trial app for you on fortrabbit. Do you want Git deployment? > Yes. You have a GitHub repo connected, and your fortrabbit account is connected to GitHub as well. Which region should the app live in, EU or US? > US! … ``` The moving parts are: ## MCP: agents - NEW The Model Context Protocol is a standard way for an agent to ask a service what it can do. Instead of teaching an agent which endpoints exist, the agent asks and gets a described list of tools back. The fortrabbit MCP server sits at: - `https://mcp.fortrabbit.com/mcp` Authorization happens in the browser. An agent can read/edit apps and environments and the reference data it needs to create one, like software presets, PHP versions, components, connected repos and branches. - :ContentLink{text="MCP setup" prefix="www" href="/mcp"} - for Codex, Cursor & VS Code - :ContentLink{text="MCP docs" prefix="docs" href="/platform/automation/mcp"} - more details ## CLI: agents, terminal, pipelines - NEW `frbit` is a single binary written in Go, no runtime dependency. Everything it does is an API call under the hood. It can also be steered by an agent (They love it). Not everything is agentic. A deployment pipeline may require exit codes and flags. That is a use case for the CLI, a boring, deterministic, good old automation. - :ContentLink{text="CLI docs" prefix="docs" href="/platform/automation/cli"} - install and commands - [github.com/fortrabbit/frbit-cli](https://github.com/fortrabbit/frbit-cli) - source ## API: base - NEW The public API offer even more automation options. REST over `https://api.fortrabbit.com/v1`, authenticated with a personal API token created in the dashboard. An API token acts as the person who created it. Apps, environments, deployments, domains, teams, people, payment methods. - [api.fortrabbit.com/v1/docs](https://api.fortrabbit.com/v1/docs) - endpoint reference - :ContentLink{text="API docs" prefix="docs" href="/platform/automation/api"} - more details ## Skills: glue - UPDATED We [shipped the fortrabbit agent skills](/introducing-agent-skills) as an early preview in April. Back then everything went through SSH and Git. Now with API and CLI the skills got a lot smarter. There are two skills now. `fortrabbit` covers the workflows: deployment, SSH, database and content sync, and MCP-based discovery and provisioning. `fortrabbit-api-access` covers the credentials — connecting an agent to the MCP server, or issuing an API token where a browser flow does not fit, like in CI. - :ContentLink{text="Agent skills docs" prefix="docs" href="/platform/automation/agent-skills"} - [github.com/fortrabbit/agent-skills](https://github.com/fortrabbit/agent-skills) ## Bring your own agent fortrabbit is BYO agent, at least until we see real benefit/need to integrate our own. Like with other aspects of fortrabbit, will we not design it as a vendor lock-in. Our aim is to keep AI features optional to support the old sacred craft of manual web development. Build great things! ## Still in BETA Mind that the whole platform is in BETA. We are dropping a lot of features at once. All of them are tested, none of them are battle proven, and there is no test like production. There will be bugs. Please report issues. We aim to respond quickly. Those are sharp tools. Use them responsibly. Stay safe kids. ## Outlook This automation suite was a bit of a detour from our main roadmap to bring feature parity and more hardening for the new platform to finally make it generally available (by removing the BETA flag). We will now turn back to that. Up next, small improvements and bug fixes, but also still missing features. I am looking forward to see dashboard metrics getting released soon. # Meanwhile at fortrabbit Source: https://blog.fortrabbit.com/meanwhile-at-fortrabbit Created: 2021-02-11 Author: Frank Lämmer Tags: changelog > HTTP/2 finally rolls out for all apps, alongside a set of smaller platform changes from the home office task force. ## Just launched ### HTTP/2 is here We have finally rolled out HTTP/2 for all Apps now. We have to admit that it took longer than we anticipated. Our first research was done in 2016 - see our blog post "[HTTP/2 reality check](/http2-reality-check)". As expected we haven't seen any major performance gains. But it's nice to have. Bear in mind that browsers will expect an HTTPS connection to servers running HTTP/2. ### Updated Craft CMS help Our Craft CMS help got a bit leaner for Craft CMS 3.6 onward. We are now featuring our own fortrabbit tooling Craft Copy more prominently. Our [issue to disable admin changes and updates on production](https://github.com/craftcms/craft/issues/61) was accepted as a new default. So with Craft CMS 3.6 less fortrabbit-specific configuration is required. Craft CMS 3.6 also integrates a [suggestion from us to structure the CLI a bit better](https://github.com/craftcms/cms/issues/7023). Nice! ### Supporting clients in the United Kingdom after Brexit While we are still struggling with some accounting related issues with Brexit, we can now more less safely say that we continue to support our clients from the United Kingdom. Both business cases, B2B and B2C, are still supported: When your UK business has tax number, add it to your Billing Contact here so that you don't have to pay VAT. We now check British VATIN against a British service. ### Easier collaboration By popular demand we have now changed the way collaboration works. It is now also possible to downgrade your own role or the role of team members of the same role. Originally we designed this to be an important feature of our collaboration tooling - just like in real life - an Owner can not downgrade the status of another Owner. Turned out that there have been too many special cases requiring our intervention. So we are opening it up now, giving you more power. Bear in mind: > With great power comes great responsibility. -Spiderman ## Soon available here ### PHP 8 We are working on bringing PHP 8 to the platform, now that it seems stable and most extensions have been upgraded. More details to follow here soon. ### No more PHP 7.2 There are still a couple of Apps running on PHP 7.2. We are planning to discontinue that version soon. Update now. ### MySQL 8 for Universal Apps We are also working on bringing MySQL 8 to the Universal Stack soon. ## Later this year ### No more MySQL 5.6 Later this year we will need to disable MySQL 5.6. More details to follow. ### PHP 7.3 EOL by the end of the year Towards the end of the year we will need to say goodbye to another PHP version: 7.3. It's still a long time until then. Plan ahead to get your Apps ready. ### Something big We are currently discussing and designing bigger platform updates. This project will take a long time. # Migration help Source: https://blog.fortrabbit.com/migration-help Created: 2015-02-26 Author: Frank Lämmer Tags: chronicles > A guide for existing users moving into the new fortrabbit dashboard: what changed, what stayed, and where to find each feature. The new fortrabbit dashboard has finally landed. This [follow up](/new-dashboard-migration-guide) guide helps existing users to explore the new features and spot the differences fast. ## Keep calm and code on **The migration is designed for hustle free upwards compatibly**. Nothing should be broken. Everything should work as before. However, we would like to encourage you to learn about the new features and workflows: 1. Update to new Company model. 2. Review if you have frozen Apps you might still need. 3. Review your code access. Read on to learn about all the goodness. ## Humanized user account model The old user model with fortrabbit V1 was flat like Twitter: Everything is an Account, you sign up with different Accounts, either personally or on behalf your company. Now, with the new fortrabbit, the user model is more like Facebook: A User is always a human being, an organization is a Company, that can be owned by Users. This way you can better map your real world relationships onto fortrabbit and work better in a team. * [Collaboration help](http://help.fortrabbit.com/collaboration) * [Multi client model backgrounds](https://medium.com/@frank_laemmer/our-multi-client-model-3b965d2f1060) ## Kill instead of freeze We changed user boarding from freemium to free trial. You can still try our service for free, but the procedure is different now: * **No more waiting slots** — always get a free tial right away * Start a trial Apps as often you want * Only have one free trial App running at a time * The official trial period is 72 hours * You can ask us to extend that trial! * Trial Apps will be terminated at the period end. Of course everything is opt-in, you will not be upgraded to a paid. * [Original announcement and backgrounds](/sunsetting-freemium) ### Frozen legacy You won't find your frozen Apps any more in the new Dashboard. That is hopefully not be a big deal as we know that 99.42% was for simple testing purposes only and you most likely have a local copy anyways. **Is there a frozen Apps you still need? Act now!** We still have all the data backed up. Please [get in touch](https://dashboard.fortrabbit.com/support) so we can send you an archive with your App's data. We will finally delete all the old frozen free Apps by the end of April 2015. ## SSH keys on Account not App We now store SSH keys with your Account. So whenever you get create a new App or get access to an existing one, your SSH key will be automatically installed. That makes managing code access much easier. We recommend to migrate the keys currently stored with your Apps into your Account. Of course: All previously installed SSH keys are still stored with the App as they were before, so nothing breaks. You can still add App-only SSH keys, since there are use-cases like external continuous integration provider which still make sense. * [About code accesss](http://help.fortrabbit.com/code-access) Also, we finally allow SSH key authentication with your App's SSH account. Previously this was only possible with your App's Git repository. Again, to make sure we break nothing: all existing Apps have still password authentication enabled. You are free to switch to SSH key only or activate both or stick with passwords. New Apps will default to SSH key only; both for Git and your App's SSH account. ## New structure, same total price We have renamed and restructured our product palette. Many of the refactoring was due to upcoming services. Your invoice will contain differently named items , but at the end of the day: the total price will be exactly the same in all cases and setups. ### Long invoices in the first month In the month of the switch (old Dashboard > new Dashboard) your invoices will be double as long as usual. That is because you have partly used the old products and are now partly using the new product structure. Again: the total sum will not change. So don't worry about it. ## Billing changes We have also integrated our own invoicing solution. The most notable change is that you can now have **multiple Billing Contacts** associated to your Company (not the Account). Sounds complicated? It's not, it's pretty much like with Amazon, where you can also manage multiple your delivery addresses and billing methods. And if you only need one billing contact, you won't even notice it. * Invoices are beautiful HTML pages now * A new invoice archive to view and download archived invoices * Invoices are now dated at the end of the service period month (that already happened with the last invoice from 2014) * You'll be notified if a payment has bounced * [Billing & accounting FAQ](http://help.fortrabbit.com/billing) ### EU B2C MOSS tax law implementation If you're not living in the EU then you can safely skip this part. We had to adapt the new [messy](http://techcrunch.com/2014/11/25/eus-new-vatmoss-rules-could-create-a-vatmess-for-startups/) EU tax regulation changes. This potentially changes for you: We only can assume that we have a professional B2B relation with you, when you supply us with your validated and verified VAT IN. Please do so, it's less stress and you don't need to pay Value Added Tax upfront. Special case: businesses from Germany, they always need to pay VAT upfront. Otherwise (no VAT IN given) we need to assume that we have a B2C relation (you use our service privately as an end user). In this case we'll add your local VAT rate on all invoices. ## Other new features * **New [professional support model](http://www.fortrabbit.com/support)** * Minimal design unifying all properties * Completely rewritten up-to-date [help pages](http://help.fortrabbit.com) * New marketing website [marketing](http://www.fortrabbit.com) * Newly designed [blog](http://blog.fortrabbit.com) * Enhanced mobile friendliness * Activties are nicer now > old activties are marked with `(legacy)` ## Please reply That's a major update for us. We hope you like it. [Feedback](https://dashboard.fortrabbit.com/support) is highly welcome! # Platform updates Source: https://blog.fortrabbit.com/minor-platform-updates-2017-06 Created: 2017-06-14 Author: Ulrich Kautz Tags: webdev > The update to the latest PHP versions caused a some downtime yesterday. First of all, let's talk about what went wrong: ## Post mortem: downtime & hiccups You might have noticed an unexpected short downtime of web delivery and Memcache and a longer unavailability of SSH/SFTP, Git yesterday — 2017-06-13. Web delivery and Memcache were down only for a couple of minutes. But about 50% of our clients were affected by the deployment issue which lasted, on and off, from around 14:00 to 17:00, then from around 21:00 until 01:00 (next day) Berlin Time (UTC+01:00). We ran a general container upgrade which was mostly about the latest PHP versions (see below) and usually runs without impact on the live system (small load variations at most). So, as this usually does not cause any downtime, the maintenance was not announced before and scheduled during standard office hours. But then… First of, there were issues with Memcache with PHP >= 7.0. In our tests before rolling out a new PHP update, we have all extensions enabled to make sure we see load- and other errors early. All tests were green, so we were confident about the roll out. While deploying the PHP upgrade in our US environment, we monitored our log servers closely so we can react to anything unforeseen immediately. We found out, that some Apps were throwing 503 errors and investigated. Within a short time, we determined that the memcached extension did not load - but only for some Apps. The reason was yet another extension: igbinary. With this current PHP upgrade, we compiled memcached, due to user request, with igbinary support, which can be used optionally. However, we did not anticipate that igbinary, even if not used with memcached, was required either way. Luckily, a patch was easy to write - we deal with cross-extension-dependencies already, so we just needed to add this new dependency and reset the App configurations. The incident was posted on our [status page](https://status.fortrabbit.com) and marked as resolved as soon as we thought the issue was solved. Memcache is only used available for our Professional Stack, which runs on different Nodes, which all were updated - all but the small development plans of Professional Apps, which share the infra with Universal Apps. Since we were at that point already engaged with another problem (see below), it took us a bit to reset the App configurations of those development Professional Apps as well. And then the next thing happened: While upgrading our EU deployment server, we saw an unusual load increase, which kept on increasing as if there is no tomorrow. We could soon identify the culprit: a faulty disk which did not deliver about any I/O. We first tried to mitigate the issue on the Node and replace the disk in the live system (using BTRFS, at least adding additional disks works like a charm - even live), but no joy: Removing the heavily used disk was not feasible. So we moved over two option number two: Replace the deployment server. That's usually quite easy, as we're on AWS and can boot new nodes in seconds, but not so for our deploy server, which holds all Apps of the region and requires much longer to set up than all other Nodes (PHP web runtime, Worker, ..). Additionally, we wanted to move the App Git repositories in their latest state from the old, still running, deployment server to the new one (in retrospective: we should have used the nightly backup instead, but once committed …). This took rather long, due to the heavy load on the old Node. Then the final problem: The setup of the new deployment server lead to a local DHCP issue, which lead to some containers having the same IP address. The nature of this incident was very tricky to identify and solve. As soon as we thought we have isolated and nailed it - it turned out we had not. To work on it, we needed to shut down the deployment node SSH server, which happened at around 21:00. That's why we have not posted updates on our status page. We're happy to say that it's now completely resolved. ### Aftermath For Professional Apps: The emergency exchange of the deployment server wiped the deployment environment of your App. This implicates that **a full Composer install will run on your next deployment**. So the next time, you'll deploy via Git, Composer will download all packages again. So the first deployment after the replacement will take a little longer as usual. This also means, before you can run any remote SSH execution like artisan migrate, you'll need to push beforehand. So when you see this on the remote: ``` A B O R T E D !! Command exited with non-zero result. Could not open input file: artisan ``` You need to `git push master` once to execute commands via ssh remote exec. ### Conclusions We are very sorry for the inconvenience. It was one the of biggest incidents of our entire history — at least the websites were up most of the time and only deployment was affected. And of course we have learned from it. We're now working on improving the deployment server setup process, as is the case for all other node types already, so that we can reliably re-create it within minutes, should something go wrong in the future. - - - Now finally, back to the main topic this post is actually about. With yesterdays update, these changes/upgrades are introduced: ## PHP versions ### PHP 7.1.5 We have upgraded the PHP 7.1.X branch to PHP 7.1.5. All new Apps will run on PHP 7.1.5 from now on per default. * [phpinfo-71.frb.io](https://phpinfo-71.frb.io) *< see the phpinfo on fortrabbit* * [PHP 7.1.15 changelog](http://www.php.net/ChangeLog-7.php#7.1.15) ### PHP 7.0.19 We have upgraded the PHP 7.0.X branch to PHP 7.0.19. * [phpinfo-70.frb.io](https://phpinfo-70.frb.io) *< see the phpinfo on fortrabbit* * [PHP 7.0.19 changelog](http://www.php.net/ChangeLog-7.php#7.0.19) ## Extensions ### ImageMagick 3.4.3 YESSSSS. The latest ImageMagick PHP extension version finally brings support for SVG. * [Release notes on PECL](https://pecl.php.net/package/imagick/3.4.3) ### Phalcon 3.1.2 The Phalcon extension has (finally) been updated as well. The new version supports PHP 7.1. So all new Phalcon software presets will run on the new version. Please update your Phalcon installation as well (see below). * [Blog post on Phalcon 3.1.2](https://blog.phalconphp.com/post/phalcon-3-1-2-released-php7-1-support) ### memcache 3.0.3 * [Release notes on PECL](https://pecl.php.net/package/memcache/3.0.3) --- ## Constant reminder to stay up-to-date Please review your Apps from time to time. Which PHP are they running on? Can you upgrade? Please mind that active support for PHP 5.6 has already ended and PHP 7 is much faster. Security support for PHP 5.6 and PHP 7.0 will also end in December 2018. At some point we will force-update legacy applications. Please upgrade PHP 5.6.x to PHP 7.1.x and PHP 7.0.x to PHP 7.1.x: ### Upgrading PHP on fortrabbit First, better test if your App works locally on the newest version. We like [Laravel Valet](https://laravel.com/docs/5.4/valet) as an easy way to run PHP 71. on macOs without containers. Then: 1. Login to the [Dashboard](https://dashboard.fortrabbit.com) 2. Go to your App 3. Go to the PHP settings 4. Change the PHP version to the latest and greatest 5. Test your application one more time 6. Enjoy the fresh air # Mission statement 2016 Source: https://blog.fortrabbit.com/mission-statement-2016 Created: 2016-06-27 Author: Frank Lämmer Tags: chronicles > Four years of PHP cloud hosting: what New Apps changed, where the company stands, and what the next year is meant to bring. ## Analysis ### New Apps into the wild Some more than a year ago we have announced [a new generation of Apps](/roadmap-to-hack-app). Half a year ago, the New Apps [launched](/new-apps-ga). And we are very happy with what we crafted: they are blazing fast, much higher available than the Old Apps, more modern, more advanced, more cloudish and last not least: more affordable (on average). The user adaption is quite OK, but to be honest here: The New Apps have not been a real smash hit until now. So what's the issue here? ### Initial expectations Part of our job is to assume which technological trends (in our space) will have an impact, so that we can start building solutions today and release them tomorrow. #### PHP movement PHP 7 is a great release — it's more sophisticated, faster and brings features which are fun to use. The performance gains are helping us using less resources and with PHP 7.1 up next, it's really a great time to be part of the PHP community. #### Our trend predictions from a year ago * PHP will become more mature & modern in general * Composer will become standard * Symfony will supply the building blocks * File abstraction will become a standard feature * Most frameworks & CMS will become "cloud-ready" * More people will want use Git for deployment ### The New Apps design After our Old Apps featured good legacy support — we finally dared to move on to a modern 12-factorish design. So the New Apps have: "[ephemeral storage](https://help.fortrabbit.com/quirks#toc-ephemeral-storage)". Which means: only Git deployment, no SFTP/SSH access to the file system. Additionally, we have launched the [Object Storage](/object-storage-launched) to offshore static assets and to compensate the lack of writable local storage (and compensate for the lack of simplicity in getting S3 up and running). ### Framework & CMS support now While PHP itself is on fire, the eco-system is moving slower than we have anticipated. Small newcomers in the scene are of course adapting quickly. But the big established projects are taking more time to catch up with the latest technology trends. And this is bad news for us, as we do not support legacy PHP style that much any more. #### fortrabbit platform compatibility levels 1. **green**: Runs perfectly here 2. **yellow**: Somehow runs here 3. **red**: Really hard to run here #### Laravel & Symfony **green**: We still love you. You are the best, but where is the rest? In general, most frameworks are compatible. #### Drupal 8 **orange**: We have been trying to get this to a easy-to-use state [for over a year now](https://github.com/fortrabbit/help/blob/master/docs/_WIP/install-drupal-8.md). To make it compatible with fortrabbits Object Storage, one need to be able to change the endpoint parameter. We submitted [a patch](https://www.drupal.org/node/2735253) to support 3rd party S3 compatible providers. That's really sad. #### Phalcon **yellow**: Why you haven't caught up with PHP 7 yet? #### WordPress **yellow**: We are impressed how little you have changed in all the years. Well, we have. And now we have not that much in common any more, which is really sad. You are one of the main reasons for the large PHP user base. PHP needs your support. But you still ignore Git and Composer. Yes, we can use [Bedrock](https://help.fortrabbit.com/install-wordpress-4#toc-install), but it's essentially a hack. File abstraction is only possible by adding two add-ons. But to work with fortrabbit it requires even an extra [add-on](https://help.fortrabbit.com/install-wordpress-4#toc-persistent-storage) for the add-on - change the S3 endpoint, of course. We know that a lot of clients want to use WP here and we are not satisfied with current solution. No hope in sight. WordPress is eventually becoming API-first, headless, or even JS-based. #### Craft CMS **yellow**: You are our hope - we see a lot of energy here. Still, it requires [a plugin](https://help.fortrabbit.com/install-craft-2#toc-setup-object-storage) (from us) to support the custom S3 endpoint to use our Object Storage. And another [extra plugin](https://help.fortrabbit.com/install-craft-2#toc-logging-amp-debugging) if you want to have logging. ### Listening to our users > Nice concepts but.... You are moving faster than your time. The PHP world is not ready yet. … —Client feedback fortrabbit is generally driven by gut decision making. We are the target group ourselves, we are itching our own scratch and dogfooding everything we do. But of course: "Gut is good, data is better." What if, when our users are not who we think they are? We set out to find out. So we have been tracking and analyzing user behavior in more depth lately, integrated a new chat tool to get more feedback and did user surveys to understand better what is really needed. Further we updated persona models and created new user stories. ### Learnings Platform features like horizontal scalability, App Secrets, Object Storage are matching the needs of sophisticated developers. These guys know how to run hosting on their own but prefer a managed service. There is also a large group of novice users who are looking for something better than shared hosting but less complicated than VPS. Those are eager to learn, but are often overwhelmed by our complexity. fortrabbit is especially attractive to host modern PHP, SaaS-like applications or backends, in Laravel or Symfony. But PHP is also a lot about classical websites, which are mainly based on WordPress. fortrabbit shines when it comes to scaling and high availability, but many projects are tiny small and don't need all that power. ## Conclusion We need to respect the double-claw hammer. PHP is a tool used by many. We need to deal with this technical debt. ## Current goals * More affordable entry level - better support for tiny Apps * Less initial complexity - unfold features when needed * Better fit for legacy workflows and applications (again) For this, we are building a new entry level App line. As far as planned, it's gonna be available by the end of the year. You will like it. Please stay tuned. # Mission statement 2023 Source: https://blog.fortrabbit.com/mission-statement-2023 Created: 2023-04-15 Author: Frank Lämmer Tags: chronicles > Ten years of PHP cloud hosting: slow steady growth, hiring difficulties, and an honest account of a quiet period without big features. ## The past years The past years brought some ups and downs for all of us. These days are not so relaxed either. Nevertheless we slowly but steadily grew our business. Bit by bit, App by App. ### People business #### Hiring challenges Attracting good people (aka talent) is not easy for us. Especially here in Germany there is high demand for DevOps and developers. We have high technical standards. We compete with big tech. Over the past years the wages have been rising. But working in a small company has its advantages as well, and we pitch that to potential candidates. With the COVID-19 pandemic we became a remote company. Hiring internationally helped us. That's also a good fit to our international client base. Diverse cultural backgrounds are sometimes challenging. Only being connected by video calls and software is hard. #### Growing pains Of course, increasing head count does not necessarily raise productivity by the same amount. It comes with overhead. And it takes time to get people boarded. Domain knowledge was traditionally also personal knowledge here. A cultural change is ongoing to share more. A knowledge base including standard procedures helps us to capture tacit knowledge into more accessible codified formats. Keeping everyone aligned and moving forward in the same direction takes extra time and effort too. New patterns are required to stay productive. #### Vision and alignment struggle fortrabbit was founded by three friends with equal rights. That works as long as there is a strong alignment in vision and actual implementation between the partners. Over the years it turned out that goals and ideas drifted apart. Finding direction became extremely difficult if not even impossible. We have spent a lot of time discussing instead of trying ideas. It was painful. We failed to find a shared direction, but we settled the conflicts by shifting power. Not the optimal solution, but something that enables us to move forward again. ### Platform challenges More clients = more responsibilities. Maintenance, support and day to day operations are keeping us busy. And then there is the hosting platform itself. It is a home-grown system that has reached maturity. It's not perfect, but it is battle proven. In recent years we have invested a lot by updating underlying software, refactoring code and improving monitoring and stability. It's still not as ideal as we wish it to be. There is a very long backlog of small improvements and documented quirks. We are also maintaining a long list of new features and big improvements. We have to admit that we were not able to keep up the pace of the early days. We can not afford to introduce breaking changes since we have websites in production. Supporting and maintaining old and new features on the same platform would become too complex a game to play. Core parts of the platform are now 10 years old. There is a lot of custom code where open source solutions are available today. The expectation of developers evolved, what was new and unique back then is standard today. Back then Let's Encrypt certs was a nice bonus, now it's a requirement. #### A New Platform to be build We have finally settled to do a bigger rewrite project. > It's easier to build the spaceship on the ground than building while flying in space. This approach certainly has its risks. But it also frees us from constraints and it enables us to approach features from new perspectives. That decision was already made more than 2 years ago. Since then we have been discussing and defining the feature set of the new platform. ## Today Now, half of the productive team time is going into the new platform, with more to come. At its core the new platform will continue our mission to provide PHPower to the PHPeople — much improved, with good backward compatibility. We are looking forward to be able to migrate over 90% of all existing clients. We are working on a final feature specification. Part of the process will be internal and external client feedback rounds. We started doing client interviews, asking for feedback on a visual mockup. Ping us if you are interested. At the same time, we have started approaching the project from the infrastructure side. On that level we are discussing and stress testing various implementation models. ## Timeline As usual, we will not provide estimates on when something is going to be finished. Even when we think something is only a week away to launch, we already know from past experience that it will take much longer. We can say that it will take at least a year from now for the new platform to launch. Then there will be a long transitioning phase to migrate existing clients over. More details will be provided along the way. Thank you for your attention. ƒrank _p.s. I struggled a while to put this online._ # New dashboard mission statement Source: https://blog.fortrabbit.com/mission-statement-the-new-dashboard Created: 2014-09-08 Author: Frank Lämmer Tags: chronicles > What to expect from the rebuilt fortrabbit dashboard, months before its release: the process, the features and the reasoning. ## Is fortrabbit still around? We have been working on our [new Dashboard](http://fortrabbit.com/feature/enhanced-dashboard) for quite a while already. It will still take months until it will be released (most likely Q1/2015). But the system is very well defined by now and i would like to share some of the process, features and changes. So that you know what to expect. Feedback is as usual also very welcome of course. ## Why a big relaunch? Well, actually we have planned to move our old system forward in small steps — a more iterative process. > … pretty much another person anyways - that idiot - I was three ago who did not write code like I do now. — [Matt Stauffer](https://www.youtube.com/watch?feature=player_detailpage&v=Qu6o4wTMo38#t=280) But you know how it is: The core code base is two years or even older by now. Our first release was a minimal viable product which was later enhanced here and there. We have learned so many things, we can't just continue with this. So this rewrite is an essential one. The whole backend architecture is being rethought and recoded. > Why do we never have time to do it right, but always have time to do it over? — Unkown On the business side we have also learned quite a few things in the past two years. So along with new dashboard will also release some changes in this area. But don't worry, we don't do crazy u-turn pivots. Instead we are zooming in a bit more. The platform will be more open, so that more people can use it. There will better workflows to make the platform even more useable in production. And last not least we have invested quite a lot of time in making the dashboard more fun to use. It's quite a powerful tool which lot's of features, but it will feel very lightweight. You will find all the pro features, just in time, when you need them. ## What will change on release? This is going to be a big release, but we are doing it step by step. First the dashboard will be launched so we have the base in place. Then in relative short time we will release follow up features. Here are some notable things that will change soon (in a few months): ### Free trial, not freemium We have [blogged about this](/sunsetting-freemium) often before. Finally we are going to remove the free developer plan. In theory it was really nice, but it never worked out as we hoped it would. Lately we had to restrict access with a waiting list. Frustration and misunderstandings on all sides. With the new trial plan you can try out the core features, if you like it you can buy it. If you need more time to evaluate the platform you can ask us and we will extend the trial. This may sound like a step backward, but we think it is a fair model. This way the system is more maintainable — you can't imagine how much time we have invested for features only needed for the freemium plan. The new trial model will also help us on our way to a more affordable entry level price, as the paid users don't have to pay for the free users any more. ### SSH keys will be stored on Account level Finally your SSH keys will no longer be stored with the Apps, they will saved with your Account. So when you create a new App you will already have access. This also helps a lot with team collaboration. During migration we will "smart guess" your SSH keys. So that you most likely don't have to reimport anything. ### A new billing system Invoicing is currently handled with Freshbooks. Freshbooks is a good service, but it's not made to send hundreds of invoices on an automated basis. We have looked for a SaaS solution especially tailored for our needs but couldn't really find one. There are many services but our needs are a bit special, as we have a bit complicated consumption based multi-seat product model. So we are building something on our own now. That's a big step for us. HTML invoices: You will get a link to the invoice instead of an attached invoice in the monthly billing mail. Invoice archive: download old invoices. ### Affordable tech support To be honest: Our current [Support as a Service solution](http://fortrabbit.com/solutions/support) with prices from 125 € / monthly is not a best seller. But support in general is a cornerstone of our business. Today most of the support we are giving is for free. Our first level tech support from the founders is helping us to convert users to clients. It's about helping people, it's about building relations, it's finding itches and edges — and it's a sales thing. But it doesn't scale very well. Like most other startups the costs for giving support should be covered with the fee for using the service. Now we would like to decouple that a bit: There are users who really want to help themselves and thus have to pay a bit less and there are other users who can book the tech support for an affordable prices. That's going to be an experiment. Let's see how it turns out. ### Much better collaboration features We have rethought the workflows to map your needs in collaborating with each other on our hosting platform. It's not only about code sharing, it's also about mapping billing and ownership. There will be Companies and Billing Contacts and it is going to be really nice. I have already blogged about that in detail [here](https://medium.com/@frank_laemmer/our-multi-client-model-3b965d2f1060). ### 3.496 other features The features mentioned here are only the big ones, the ones you should know about in advance. There are many more nice things on the way. ### We keep you in the loop We will inform you again about upcoming changes in time, individually. Speaking of sunsetting: We will also phase out A-record entries for domains. Of course the old IP addresses will still work for quite a while, but please don't use them from now on any more. Please use CNAME entries instead. This allows us to move your App around in a much more flexible way leading to better uptime and a more resilient setup. ## What will be added after the release? There are quite a few features wich we are planning to add shortly after the initial release of the new dashboard; stuff that doesn't made it on the roadmap short list; things that are already prepared but not quite ready for prime time yet: ### Ephemeral App plans That's THE major change we are already planing for a long time. We started out as the PHP PaaS supporting the default workflows SSH and SFTP besides Git. That was an unique value proposition at the beginning. Now we see so much progress in the PHP scene and we think that it is about time to move over to a more advanced stack. The storage will be ephemeral, the system will be even more reliable, even faster in performance and more affordable. The first iteration of the architecture will be called [Hack-App](http://fortrabbit.com/feature/hack-app). ### HHVM Speaking of Hack: yes we also still plan to make [HHVM available](http://fortrabbit.com/feature/hhvm-support). Intrinsically we have planned to launch the Hack App only on HHVM, but we now think it is better to separate the two things. Mostly to get things out sooner. We love to see that HHVM is getting more stable and more predictable, for instance with [longtime support](http://hhvm.com/blog/6083/hhvm-long-term-support) and we are looking to make it available in away that it can be used in production. ### US launch The new backend architecture is better maintainable, better capable of running in multiple infrastructures and we can run it with less overhead. We also abstracted for multi-cloud capability. So that fortrabbit will possibly also be able to run on a different infrastructure layers than AWS, speak: Rackspace, Digital Ocean and alike. And: we have added support for multiple currencies, speak: prices in USD. There is more todo for launching in the US, but some of the essential ground work will be done. ### API The idea is around for a while. With the new dashboard we are already eating out own dog food by using an internal API. So the public API is not so far away any more. The launch date depends on how fast we'll be able to write a good documentation. Thanks for reading so far! # Modern PHP monoliths Source: https://blog.fortrabbit.com/modern-php-monoliths Created: 2025-11-11 14:17:01 Author: Frank Lämmer Tags: opinion > Interactive interfaces without splitting the stack: how a modern PHP monolith competes with a decoupled headless architecture. ## What's a modern monolith? The cool kids create headless systems, where frontend and backend are fully separated, loosely connected by an API. See our [headless PHP](/headless-php) post on decoupled systems with PHP. But some developers questioned decoupled headless systems. Why not use existing tooling? Or why not even send HTML over the wire? The author of Inertia.js describes his idea like so: :ContentQuote{ author="Jonathan Reinink" text="It allows developers to build rich single-page client-side apps, without having to build a full REST or GraphQL API, or learn client-side state management, routing, and really much of what comes with modern SPAs." } One benefit is making use of the battle-tested tooling that comes with modern PHP frameworks and CMS: routing, authentication, ORM. The other is that such systems are easier to set up, host and deploy: one codebase and one hosting environment. ## Architecture Unlike headless systems, modern monoliths are coupled together. There are different approaches to do this. - Magic: Freeing backend-oriented developers from dealing with JavaScript. - Glue: Connecting frontend and backend, removing the API requirement. ### A - Livewire The aim of Laravel Livewire is to enable PHP developers to create modern reactive websites without having to leave the PHP world at all. The logic is written in PHP, while the templates are also still in Blade, but with superpowers to enable live partial updates and reactivity. - [laravel-livewire.com](https://laravel-livewire.com/) ### B - Inertia.js Inertia.js, also hailing from the Laravel scene, has a different approach. It glues together the PHP backend with a JavaScript frontend, think Vue.js, React or Svelte based systems. Unlike with decoupled systems, the data is directly provided by the PHP layer, no need for an API. There is an adaptor for each JavaScript framework. Inertia supports SSR (Server Side Rendering), but it requires a Node.js runtime running alongside PHP. - [inertiajs.com](https://inertiajs.com/) ### C - Symfony UX The user experience layer from Symfony is a mix of different technologies and boilerplate. It contains some common components for maps, icons and charts that can be directly used. Live components bring reactivity in a similar way as Livewire. It also includes the Hotwire (37signals) modules Turbo and Stimulus. - [ux.symfony.com](https://ux.symfony.com/) - [hotwired.dev](https://hotwired.dev/) #### AssetMapper AssetMapper is a PHP library used and recommended by Symfony to compile frontend assets in PHP - Node.js not required. It also acts like a package manager and provides Twig tags to link to versioned asset versions. The older alternative uses Webpack Encore. See [Symfony docs](https://symfony.com/doc/current/frontend.html#stimulus-symfony-ux-components). ### D - Datastar Datastar is a new framework, which is primarely a small JavaScript library that can be pulled in by CDN. It's backend agnostic and has connectors (SDKs) to Laravel, Craft CMS and others already. It has a paid Pro version and it claims to solve more problems than it creates. - [data-star.dev](https://data-star.dev) ### E - HTMX and derivates [HTMX](https://htmx.org) and [Unpoly](https://unpoly.com/) are also a backend-agnostic JavaScript libraries, adding reactivity without too much change on the backend side. Too dive even deeper, have a look at [Hypermedia Systems](https://hypermedia.systems/) - a book that it looks at HTMX and Hyperview. Somehow also in this space are the following projects: - [Sprig plugin for Craft CMS](https://putyourlightson.com/plugins/sprig) - based on HTMX - [YoYo](https://getyoyo.dev/) - based on HTMX - [Nuxt Kirby](https://nuxt-kirby.byjohann.dev/) - data bridge for Kirby CMS and Nuxt, headless + monolith ## My takeaway Modern monoliths are a great alternative to [headless systems](/headless-php) and an improvement over classical page by page websites. This is not about winners and losers. This is about team size, requirements and most of it all personal preference and skills. Many developers stick to their home stack. My observation: - Backend-focused devs try to get away without too much frontend. - Frontend-focused devs try to get away without too much backend. That's why specifically the magic systems are attractive to backend-focused developers. We are currently building our [new platform](https://new.fortrabbit.com). One of the next features we want to add is Node.js that can be called through PHP (on a worker job), required to make Inertia.js work with SSR mode. --- ## Appendix | System | Type | Node.js via PHP `*` | Node.js deployment `**` | | ---------------- | ----- | ------------------- | ------------------------ | | Laravel Livewire | Magic | No | No | | Inertia.js | Glue | Yes | Yes | | Symfony UX | Magic | No | [Optional](#assetmapper) | | Datastar | Magic | No | No | | Sprig (Craft) | Magic | No | No | | Yoyo | Magic | No | No | ### Legend - `*` Node.js via PHP - PHP talks to a backend Node.js process (worker) - `**` Node.js deployment - `npm run build` to generate artifacts # How and why we moved our knowledge base from Notion to Markdown Source: https://blog.fortrabbit.com/moving-knowledge-base-from-notion-to-markdown Created: 2026-06-11 15:02:41 Author: Frank Lämmer Tags: chronicles > Why we left Notion for a folder of Markdown files, and the gotchas we hit along the way. ## Motivation There is nothing wrong with Notion. I still enjoy using it privatly. In the beginning, it felt like a very capable Markdown editor with nice abstractions. Over the years though, it got a bit too crowded for my taste. We used Notion as our knowledge base and partially for project management for years. The knowledge base part is what we cared about the most. Hopefully, these thoughts are usefuls for others. Side note: I can imagine Microsoft buying them at some point. There is a lot about Office that is antiquated and Notion could fill that gap (Hello Notion CoPilot!). ### Ownership over our content Freedom of tools. Content rules. Some of us use [Obsidian](https://obsidian.md/) to edit, but the same folders open in any code editor. I enjoy writing Markdown. I do it for the blog and the docs every day. Keeping the knowledge base in the same format removes friction. ### Saving costs Our internal structures changed and require less ongoing work on internal policies. We also adopted Linear for project management (hello next vendor lock-in). So Notion was neglected. It can also be hard for humans to find information in a large knowledge base, or to keep parts of it up to date. We already pay for an AI subscription. Paying extra for Notion AI on top was never something I wanted to do. ### Privacy The files are ours now. Full data sovereignty. But we still want to share them across the team, so we trust a Git repo provider with the content (Obsidian sync is another option). When we run batch edits with AI, we may leak data to whichever provider we use. But we do not store secrets in our knowledge base — no API keys, no passwords, no trade secrets. ## How we moved We used the Obsidian Importer plugin and the Notion API flow. There are plenty of tutorials on how to do that, so we will skip the basics and stick to the gotchas. ## Missing internal links A significant number of internal links broke during the import. Incremental imports left links pointing to `NOTION_PAGE:(UID)` references that no longer resolved. I fixed most of them with a local AI agent. About 150 broken links remained. I checked many of them manually and found they were either broken in Notion already or pointed to trashed documents. Good enough. ## Team spaces to vaults In Notion, we had a few "team spaces" with separate access management. In Obsidian, the rough equivalent is a vault - think of it as a Git repo. We decided one mono-vault without access management beats multiple vaults. Searching and linking across vaults is not easy, and a flat structure matches how we actually work. ## Assets Notion abstracts files away. It is all content. With Obsidian, files are real things you have to think about. We created one global `Assets` folder and put everything in it. Most of it is images, and we plan to use fewer files going forward. ## Databases Notion databases are very capable and cool. Obsidian recently added databases too, but they are way more basic. The concepts are different. We will see how useful they turn out to be in practice. I already miss the fancy databases. ## File structure The file structure works differently. The relation between a database and its entries shows up in the file system — each entry exists as its own file. That takes some time getting used to, but it makes the content portable. ## Web forms We used Notion web forms to accept job applications. We need a different solution for this. Open task. ## No real-time collaboration We can no longer co-edit a document live during a meeting. We will see how much we miss it. Our hunch: less than expected. ## Other Notion features We did not use Mail or Calendar in Notion. We will not miss those. ## Takeaway Owning the files matters more than we expected. Plain Markdown in a Git repo means we can search it, edit it with any tool, version it like code, and pipe it through AI when we want to. # Multi stage deployment Source: https://blog.fortrabbit.com/multi-stage-deployment-for-website-development Created: 2012-10-01 Author: Ulrich Kautz Tags: webdev > How to setup a production/development work-flow for website development. UPDATE 2021: There is also a new [help page](https://help.fortrabbit.com/multi-staging). This article targets new developers and developers which never had the chance working with multi versioned websites before. If this fit's you: Read it. Staging is a good tool in your belt you won't regret to know. ## What staging is all about Staging has many [meanings](http://en.wikipedia.org/wiki/Staging), I will focus only on those in the context of website development. Wikipedia [defines](http://en.wikipedia.org/wiki/Staging_%28websites%29) a staging site as a website used to assemble, test and review its newer versions before it is moved into production. To put it in other words: You've installed your website on two different places (aka deployments or environments). One installation is called **production** (or sometimes _live_) : This is your live website. Users are visiting it and interact with it. The other installation is called **staging**: You, your co-developers, authors and whatnot using it to prepare and test stuff which is to be released into production. In short: you do not perform open-heart surgery by coding directly on the production website. Other keywords in the context might be: "App live cycle management", "one codebase many deploys". ## Multi staging / multi level deployments Depending on the size of your project, sometimes you need more deployments. It's best explained with use cases. ### Purpose separation The bigger the team working on the site, the more specialized each member tends to become. There are designers, editors, programmers, controllers - you name it. If you've worked / are working in a team of more than two people, surely you have experienced the following: The coders are working on the (non production) site. Something breaks temporarily. The programmers know, that this is temporarily, the designers, authors and everybody else do not. So they either file bug reports, which annoys the programmers, or they stop working, which wastes time. Both is bad: It breeds bad temper and costs time and money. Thats why, as soon as the team size warrants it, there should be more deployments - at least one for each team. However, keep in mind that the structure / amount of the deployments should be designed based on the needs and conditions of your project. Do not put more levels in than you can handle. [Here](http://en.wikipedia.org/wiki/Development_environment_%28software_development_process%29) is the general definition of development environments from Wikipedia. ### Example: Three level deployment This one I've used quite a lot. It works good with a team of three or more. - **Development**: A space for coders where they can break things without being afraid of complains by the rest. - **Staging**: Where new code, which is finished (aside from bug fixing), can be deployed so everybody can review/test it before it is released. Also less destructive implementations (eg CSS changes) can be done. - **Production**: The live website - no bugs nor half-backed content here (hopefully). ### Example: Four level deployment If the team gets bigger and there is money for dedicated testers: - **Development**: A space for coders where they can break things without being afraid of complains by the rest. - **Testing**: Designated testers review the updates made in development. Test suites are run. - **Staging**: Only final review is done, no active development. - **Production**: The live website - no bugs nor half-backed content here (hopefully). ### Feature development When deployments are easy to setup, it lend itself to outsource feature developments in dedicated environments. The bigger the new feature and the more core changes it requires the more should you consider this. Also sometimes you want to try out some bigger changes, which might not ever make it to production (if they fail to to what you want). Either way, feature deployments make sense, because they to not interfere with the regular development or (even more important) bug fixing. If you are in the middle of a core changing feature which is weeks away from being stable, really don't want to push it online, just because you need to fix a critical bug. ### Right separation Most [content management systems](http://en.wikipedia.org/wiki/Content_management_system) implement already a kind of right separation: An author/editor is allowed to write an article but only the executive editor can publish it. However, in the context of code development, this is not the case. Assume you are the CTO of a company and hire two new coders. You might not want them to to publish code into production, as you don't know judge their skill level or some company policy prohibits you to do so. So taking the four level model from _Purpose separation_ above, the new guys can only access the development deployment, whereas more senior staff is allowed to publish into staging. You alone are responsible for the live environment - so you alone can publish onto it. ## The data synchronization problem Runtime data, such as images uploaded by users, database rows generated by user interaction and so on, is the most difficult problem to solve in multi level deployments. General there are two possibilities: Your data is shared or it is not. In development and/or testing deployments, you really can mess up the whole system. What you want here is data separation: different database, cache and file storage. What you want is a simple one way synchronization (production -> development), so you can rebuild your destroyed development very fast. Normally it is not required to have live data, so using the last night backup as base for this is a good idea. In staging or authoring levels, it is sometimes necessary to use exactly the same data as in production. Still, try not to do this - or at least be aware what you are doing. ## Downside of multiple environments Yes, there are some. The impact is in general greater, the more you overreach in the amount of deployments you really need vs the amount of deployments you have. ### Delay Multi stage environments delay the deployment of a particular line of code as they have to pass multiple levels. Depending on how strict you enforce them, it can take days until a simple wording change is published. This can yield bad behavior, eg that minor (deemed) changes are dropped completely. The time delays and omitted changes will cost you money and can reduce the overall quality of your application. The solution for this strongly depends on your (company's) policies and the possible impacts (money loss) if you'd relax those. ### Complexity > Make everything as simple as possible, but not simpler. Albert Einstein Having multiple environments adds additional levels of complexity. You can make new mistakes based on the different infrastructures your app is in. Same as above: Don't over-egg the pudding. ## Bottom line Staging is a tool as any other: Use it with care. Do not overdo, but also do not downplay it's need / purpose to the last minute. In my opinion, you should at least plan ahead for multi level deployment. Implement application level recognition of the deployment early on (in a sense `if in_staging: use staging database; else: use production database`). ## A great proposal: Git flow In the context of modern web development and deployment, you should probably know about the [Git flow](https://github.com/nvie/gitflow) Git extensions, which are based on the proposal of a [successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/). At this time, Git flow does not address deployment at all, but it's proposed branching model gives you a good structure to start on. # MySQL 8.4 upgrade plan Source: https://blog.fortrabbit.com/mysql-8-4-upgrade-plan Created: 2026-05-26 11:00:00 Author: Erin Strand Tags: changelog > Two ways to upgrade an app on the old fortrabbit platform from MySQL 8.0 to 8.4, now that 8.4 is the default for new apps. This article only applies to the old platform, our [new platform](https://dash.fortrabbit.com/) already uses MySQL 8.4. On the OLD platform MySQL 8.4 is now used by default for all new Apps and MySQL 8.0 is being deprecated. - applies to all Uni and Pro Apps in EU and US (old platform) - existing Apps using MySQL 8.0 keep using MySQL 8.0 until [automatic upgrade](#automatic-upgrade) - manually upgrading your MySQL 8.0 plan to 8.4 is now possible, read more below ## Automatic upgrade In week 25, starting June 22 2026 we will automatically upgrade all remaining Apps that are still on MySQL 8.0 to MySQL 8.4. Subscribe to status updates: [status.fortrabbit.com](https://status.fortrabbit.com) Please take the time to test and upgrade before this deadline to make sure that your Apps will work properly with MySQL 8.4. ## Breaking changes in MySQL 8.4 MySQL 8.4 brings a few breaking changes that might cause your database to fail upgrading from MySQL 8.0 to 8.4. ### Foreign keys require unique index The target column of a foreign key must now have a unique index applied. This will not block the upgrade, but any new tables or foreign keys you create will have to follow this rule. This is fairly easy to resolve, you just have to add a unique index to your target columns. This have always been the expectation, and it is now enforced to ensure that the database always has a clear answer to which unique row your foreign key refers to. ### New reserved words Four new words are now reserved (MANUAL, PARALLEL, QUALIFY, TABLESAMPLE), meaning you can only use them as table, column, index or stored procedure names when they are properly quoted. But it is probably best to not use them at all if you can avoid it. ```sql -- Will not work in 8.4 SELECT manual FROM manual; -- Will work in 8.4 SELECT `manual` FROM `manual`; ``` ### Float/double cannot be auto incremented Columns of type float and double can no longer have `AUTO_INCREMENT` applied. If you have this upgrading will fail. This is a very unusual configuration, but if you happen to use this odd setup, be sure to change your auto incrementing column types to INT or BIGINT before upgrading! ### Queries to check for all breaking changes Not sure if you use any of these deprecated settings in your database? Here is a handy set of queries to double check! ```sql -- Check if we have float/double auto increment columns SELECT table_schema, table_name, column_name, data_type FROM information_schema.columns WHERE extra LIKE '%auto_increment%' AND data_type IN ('float', 'double'); -- Check if mysql host has tables with foreign keys with missing unique index SELECT kcu.CONSTRAINT_SCHEMA AS `database`, kcu.TABLE_NAME AS child_table, kcu.CONSTRAINT_NAME AS fk_name, kcu.REFERENCED_TABLE_NAME AS parent_table, kcu.REFERENCED_COLUMN_NAME AS parent_column FROM information_schema.KEY_COLUMN_USAGE kcu JOIN information_schema.REFERENTIAL_CONSTRAINTS rc ON rc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND rc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA WHERE kcu.REFERENCED_TABLE_NAME IS NOT NULL AND kcu.CONSTRAINT_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') -- Exclude FKs where the referenced column has a unique or primary key AND NOT EXISTS ( SELECT 1 FROM information_schema.STATISTICS s WHERE s.TABLE_SCHEMA = kcu.CONSTRAINT_SCHEMA AND s.TABLE_NAME = kcu.REFERENCED_TABLE_NAME AND s.COLUMN_NAME = kcu.REFERENCED_COLUMN_NAME AND s.NON_UNIQUE = 0 -- 0 means unique (includes PRIMARY KEY) ) ORDER BY `database`, parent_table, fk_name; -- Check if mysql host has tables/columns/indices/prodecures using new forbidden words SELECT t.TABLE_SCHEMA AS `database`, t.TABLE_NAME AS `table`, 'TABLE' AS `type` FROM information_schema.TABLES t WHERE UPPER(t.TABLE_NAME) IN ('MANUAL','PARALLEL','QUALIFY','TABLESAMPLE') AND t.TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') UNION ALL SELECT c.TABLE_SCHEMA AS `database`, CONCAT(c.TABLE_NAME, '.', c.COLUMN_NAME) AS `table`, 'COLUMN' AS `type` FROM information_schema.COLUMNS c WHERE UPPER(c.COLUMN_NAME) IN ('MANUAL','PARALLEL','QUALIFY','TABLESAMPLE') AND c.TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') UNION ALL SELECT s.TABLE_SCHEMA AS `database`, CONCAT(s.TABLE_NAME, '.', s.INDEX_NAME) AS `table`, 'INDEX' AS `type` FROM information_schema.STATISTICS s WHERE UPPER(s.INDEX_NAME) IN ('MANUAL','PARALLEL','QUALIFY','TABLESAMPLE') AND s.TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') UNION ALL SELECT p.SPECIFIC_SCHEMA AS `database`, CONCAT(p.SPECIFIC_NAME, '.', p.PARAMETER_NAME) AS `table`, 'PROCEDURE_PARAM' AS `type` FROM information_schema.PARAMETERS p WHERE UPPER(p.PARAMETER_NAME) IN ('MANUAL','PARALLEL','QUALIFY','TABLESAMPLE') AND p.SPECIFIC_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') ORDER BY `database`, `type`, `table`; ``` ## MySQL upgrade methods Here are two workflows on how to upgrade the MySQL version of your App: ### Uni Apps For Uni Apps you change the MySQL version by upgrading your plan. This method has zero downtime, but your database will be marked read only for the duration of the migration. 1. Download an up-to-date backup of your MySQL database - If you have backups enabled, you can download a zip file from the Dashboard - You can also manually dump the database using a [mysql client and our tunnel](https://help.fortrabbit.com/mysql#toc-access-the-mysql-database-from-local) 2. Upgrade your local development environment to MySQL 8.4 3. Test your project in your local environment and ensure everything works (Important!) 4. Click "Upgrade" in the dashboard for your app, select the same or a different plan, and migration to MySQL 8.4 will start 5. Our system will handle the migration for you, your database will be made read only until the migration finishes. If you have any issues, reach out to us in support. ### Pro Apps For Pro Apps you change the MySQL version by changing the MySQL Component plan. This method has zero downtime, but your database will be read only for the duration of the migration. 1. Download an up-to-date backup of your MySQL database - If you have backups enabled, you can download a zip file from the Dashboard - You can also manually dump the database using a [mysql client and our tunnel](https://help.fortrabbit.com/mysql#toc-access-the-mysql-database-from-local) 2. Upgrade your local development environment to MySQL 8.4 3. Test your project in your local environment and ensure everything works (Important!) 4. Click the MySQL component in dashboard for your app, scale it to the same or bigger size, and migration to MySQL 8.4 will start 5. Our system will handle the migration for you. If you have any issues, reach out to us in support. ### Migrate to the new platform You can also take the opportunity to try out our new platform. It already runs on MySQL 8.4 and PHP 8.5, so you can migrate your App there to get the latest tech! 1. Download an up-to-date backup of your MySQL database - If you have backups enabled, you can download a zip file from the Dashboard - You can also manually dump the database using a [mysql client and our tunnel](https://help.fortrabbit.com/mysql#toc-access-the-mysql-database-from-local) 2. Upgrade your local development environment to MySQL 8.4 3. Test your project in your local environment and ensure everything works (Important!) 4. [Sign up for the new platform](https://dash.fortrabbit.com/signup) 5. Create a new app (MySQL 8.4 is used by default) 6. Deploy the project (code, assets and database) to the new app 7. Test your project on the new app and ensure everything works 8. Switch DNS entries to the new app 9. Once you see that everything works, delete the old App ## Related help articles - [Local development](https://docs.fortrabbit.com/integrations/local-development) - set up a local development environment - [Main MySQL article](https://help.fortrabbit.com/mysql) - connect to the fortrabbit database from your local machine and download the database - [Downloading an App](https://help.fortrabbit.com/downloading-an-app) - download all the content from your App # MySQL 8 is now available for Pro Apps Source: https://blog.fortrabbit.com/mysql-8-now-available-for-pro-apps Created: 2020-10-28 Author: Frank Lämmer Tags: changelog > We are finally making MySQL 8 available. What clients need to know about the roll-out. ## What's new in MySQL 8 Compared to MySQL 5.6, MySQL 5.7 and MySQL 8 have some nice features you might want to use. For example: * Improved JSON support: Directly manipulate JSON data within your MySQL database * Emoji support: 🤩 * Better handling of GeoSpatial data types for working with geographic data ### Target audience Many of our clients are using a CMS like Craft CMS or WordPress. In that case, you might not need to bother too much about this. For Symfony or Laravel users building custom applications the new features might come in handy, and the effort required to update your application might be worth the time. ## Now * All existing Pro Apps will stay on MySQL 5.6 (for now) * All new Apps created on the Pro Stack will run on MySQL 8 * To upgrade your App see the [Upgrade section](#upgrading) below ## Next * Universal Apps will receive the same upgrade at a later date when we have ensured that everything works well * We plan to phase out MySQL 5.6 at some point (see [EOL section](#eol) below) ## Upgrading We recommend the following workflow to get your App up and running with the new version of MySQL: 1. Create a new App with the fortrabbit Dashboard 2. Push your existing code to the new App (and import database) 3. (Update your local development environment setup to MySQL 8) 4. Test if everything is working correctly 5. Once you know it works, switch the domain 6. After that, delete the old App - it's not required any more Please ping us if your have any questions along the way. We are also happy to give you an individual discount so that you don't have to pay double during the migration period. Take this as an opportunity to update the rest of your application as well. ## End of life for MySQL 5.6 We will eventually switch off MySQL 5.6 at some point. The official End Of Life for MySQL 5.6 is February 2021. We plan to support it longer than that, but no date for deprecation has been set yet. Further communication from us on the topic will follow. ## Heads-up for Sequel Pro users On macOS the free MySQL client Sequel Pro is very popular. There are some issues with MySQL 8 and Sequel Pro: [see this StackOverflow question](https://stackoverflow.com/questions/51179516/sequel-pro-and-mysql-connection-failed). We suggest using a different local MySQL client. [Sequel Ace](https://github.com/Sequel-Ace/Sequel-Ace) is a Sequel Pro fork with MySQL 8 support, for example. # MySQL 8 upgrade plan Source: https://blog.fortrabbit.com/mysql-8-upgrade-plan Created: 2021-04-07 Author: Oliver Stark Tags: changelog > How to move an app from MySQL 5.6 to MySQL 8 on fortrabbit, including the platform-side migration workflow added later. UPDATE 2021-06-17: We have now enabled a migration workflow which is running on our platform. See below for [Method 3](#method3). ## Current state MySQL 8.0 is now enabled for all new Apps created on the fortrabbit platform and MySQL 5.6 is being deprecated. ### Universal Apps + no action required + all newly created Universal Apps use MySQL 8.0 since April 2021 + older Universal Apps using MySQL 5.7 will keep using MySQL 5.7 (even when upgraded to our Standard or Plus plans) + we will keep supporting MySQL 5.7 on Universal Apps for the foreseeable future ### Professional Apps + action required for Apps created prior April 2021 + all newly created Professional Apps use MySQL 8.0 + scaling up or down MySQL 5.6 plans is no longer possible + automatically upgrading your MySQL 5.6 plan to 8.0 is possible, read more below + on the 13th of July we will start force upgrading all remaining 5.6 plans to 8.0 ## Deadline On the __13th of July__ we will force upgrade all remaining Professional Apps that are still on MySQL 5.6 to MySQL 8.0. Please take the time to test and upgrade before this deadline to make sure that your Apps will work properly with MySQL 8.0. ## MySQL upgrade methods Here are two workflows on how to upgrade the MySQL version of your App: ### Method 1 - New App with MySQL 8 This is the safest workflow and uses a new App for the new MySQL version. This method causes some downtime when switching your domains. 1. Download an up-to-date backup of your MySQL database + If you have backups enabled, you can download a zip file from the Dashboard + You can also manually dump the database using a [mysql client and our tunnel](https://help.fortrabbit.com/mysql#toc-access-the-mysql-database-from-local) 2. Upgrade your local development environment to MySQL 8 3. Test your project in your local environment and ensure everything works 4. Create a new App with MySQL 8 5. Deploy the project (code, assets and database) to the new App 6. Test your project on the new App and ensure everything works 7. Switch DNS entries to the new App 8. Once you see that everything works, delete the old App ### Method 2 - Switch existing App (Pro Apps only) This is also a safe workflow, but only applicable for Pro Apps. Here you work with one App and change the MySQL version by un-booking and booking the MySQL Component. This method also causes some downtime while MySQL is offline. 1. Download an up-to-date backup of your MySQL database 2. Upgrade your local development environment to MySQL 8 3. Test your project in your local environment and ensure everything works 5. Un-book MySQL completely with the App 6. Book a MySQL again, it will be on MySQL 8 7. Import the database dump you created earlier ### Method 3 - Use our automatic migration (Pro Apps only) This is a less safe workflow. The beauty is that it does not involve much action from your side. This method also causes minimal downtime, as only write access is removed while the database migrates to a new Node. 1. Download an up-to-date backup of your MySQL database 2. Upgrade your local development environment to MySQL 8 3. Test your project in your local environment and ensure everything works 4. In our Dashboard with your App, go to the MySQL scaling page 5. Choose a new MySQL 8 plan and hit the book now button (book the same size) 6. Wait 5 minutes until the operations are complete. We can not guarantee that our database migration will work perfectly for every database, which is why the manual migration above is the safer option. ## Related help articles + [Local development](https://help.fortrabbit.com/local-development) - set up a local development environment + [Main MySQL article](https://help.fortrabbit.com/mysql) - connect to the fortrabbit database from your local machine and download the database + [Downloading an App](https://help.fortrabbit.com/downloading-an-app) - download all the content from your App ## Related from the web + [MySQl 8 upgrade plan by FromDual](https://fromdual.com/upgrade-mysql-5-7-to-my-sql-8-0) + [Official MySQL 8 upgrading docs](https://dev.mysql.com/doc/refman/8.0/en/upgrading.html) # MySQL 8 upgrades Source: https://blog.fortrabbit.com/mysql-8-upgrades Created: 2023-06-05 11:02:19 Author: Frank Lämmer Tags: changelog > The last remaining apps move from MySQL 5.7 to MySQL 8 in a long-running maintenance project. What clients need to do, and when. We started the [path to MySQL 8](/mysql-8-upgrade-plan) back in April 2021. Now it's time to move the last remaining Apps to MySQL 8. So far we have good experiences with it and we are able to migrate almost all Apps without any issues or client involvement. There is good upward compatibility. ## Rundown Within the next weeks, we will post MySQL maintenance windows on our [status page](https://status.fortrabbit.com). The 5.7 to 8.0 MySQL migration is only required for a small number of Apps. Expected downtime for each App is only a few seconds. ## MySQL 5.7 grace period UPDATED: 2023-09-06 - We have allowed a small number of Apps to continue to run on **MySQL 5.7 up until the 4th of October 2023**. Then we will update the last remaining Apps to MySQL 8. We saw that all remaining Apps broken with MySQL 8 are running on outdated software. All major software systems (Craft CMS, Laravel, WordPress …) are supporting MySQL 8 with all maintained releases. This applies also to older major releases. For example, Craft CMS 3.4.x does not support MySQL 8, but the current version of version Craft CMS 3, which is 3.9.x does supports MySQL 8. The latest major version of Craft CMS is 4. We are doing a mailing to inform all Owners of Apps not yet ready for MySQL 8. ### How to upgrade Most likely all that needs to be done is running a `composer update` locally, test and deploy the latest version to the App to be ready for MySQL 8. You can also deploy the code to a newly created App to test for compatibility. If you don't have a local development setup, you may also just hit the update button with the control panel of your software directly. See our [best practice to update Craft CMS](https://help.fortrabbit.com/craft-update) driven websites. ### Update to PHP 8 as well Once you have now upgraded your software, consider updating to PHP 8 as well. It's likely that this App is also running on PHP 7.4. PHP 7.4 is already deprecated and will be removed next. See our [PHP version upgrade](https://help.fortrabbit.com/php-version-upgrade) article. ### We are here to help Please do not hesitate to contact support with specific technical questions or issues. # MySQL Backups for Pro Apps Source: https://blog.fortrabbit.com/mysql-backups-for-pro-apps Created: 2017-02-14 Author: Ulrich Kautz Tags: changelog > Automated MySQL backups become bookable for Professional Apps, after the feature shipped with the Plus plan on Universal Apps. An often requested feature for Professional are MySQL backups. They are now, finally, available! MySQL backups can be booked per App in the Dashboard > Your App > Scaling > MySQL. On the Upgrade screen, check **Backups enabled**. You can enable backups for both existing Professional Apps and newly created Professional Apps. ![Enable backups](/images/mysql-with-backup-on.png) Backups cost additional €5 (or $5, if you are using USD) per App with MySQL components in Production level scaling and +8% with Dedicated level scaling. All prices can be viewed on the [specs page](https://www.fortrabbit.com/old-platform/specs-pro#mysql). One day after enabling backups for an App, you can download them from:
Dashboard > Your App > MySQL Backups ![Download backups](/images/mysql-backups-2.png) Backups are generated every night (for exact timing, see [specs](https://www.fortrabbit.com/old-platform/specs-pro#mysql-backups)) and will be kept for download for 30 days. ## No impact, no hassle Backups are created from snapshots of the databases. Those snapshots are taken nightly and do not affect the database performance at all, because they are made of the underlying file server by AWS. We start new database instances from those snapshots and dump the backups from those instances. **This means:** Your live application is _not_ impacted in the least. # MySQL with JSON in Laravel Source: https://blog.fortrabbit.com/mysql-json-column-with-laravel Created: 2020-12-08 Author: Oliver Stark Tags: webdev > JSON columns let MySQL hold data that does not fit a strict schema. How to declare, query and cast them from a Laravel application. ## Why JSON columns? MySQL, like any other relational database, is great at modelling data structures and making connections between them. But what if there is some parts of your data that does not fit into a relational model - data that does not follow a strict schema? You could opt for a NoSQL database like MongoDB, that is optimized for storing JSON-like documents. But the truth is you don't need another database. MySQL has had a built-in JSON column type since 5.7, and a lot of improvements have been introduced with the 8.0 release. This hybrid approach is not new - PostgreSQL has supported JSON since 2013. ## RAW SQL - preparation To understand what you can do with JSON columns, let's create a table with a `meta` JSON field and also a reference to an imaginary users table. (Feel free to ignore the `user_id` field: it's just there to show that we can mix relational data and JSON objects in a single table.) ``` CREATE TABLE things ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, meta JSON, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` We also need some dummy data to play around with. If you take a look at the `INSERT` statements below, you will notice that the values we insert into the `meta` fields look like strings. ``` INSERT INTO things (user_id, meta) VALUES(100, '{"single": "Towel", "many": ["Toilet Paper", "Mirror", "Soap"]}'); INSERT INTO things (user_id, meta) VALUES(200, '{"single": "Gingerbread", "many": ["Clotted cream", "Fruit fool"]}'); INSERT INTO things (user_id, meta) VALUES(300, '{"single": "Table", "many": ["Sideboard", "Bench", "Wardrobe"]}'); ``` To validate the inserts, let's query the whole table: ``` SELECT * FROM `things`; +----+---------+--------------------------------------------------------------------+---------------------+ | id | user_id | meta | created_at | +----+---------+--------------------------------------------------------------------+---------------------+ | 1 | 100 | {"many": ["Toilet Paper", "Mirror", "Soap"], "single": "Towel"} | 2020-12-01 10:00:41 | | 2 | 200 | {"many": ["Clotted cream", "Fruit fool"], "single": "Gingerbread"} | 2020-12-01 10:00:42 | | 3 | 300 | {"many": ["Sideboard", "Bench", "Wardrobe"], "single": "Table"} | 2020-12-01 10:00:43 | +----+---------+--------------------------------------------------------------------+---------------------+ ``` As you can see, there is nothing special so far. The `meta` fields look like the JSON encoded strings we inserted previously, just like any other column with string data type `TEXT` or `VARCHAR`. However, under the hood MySQL stores the values in a binary format and validates the documents when inserting or updating them. Which means, if you try to insert invalid or broken JSON, you will get an `Invalid JSON text` error. ## Raw SQL - JSON queries So far we gained almost nothing from the JSON columns, except a bit of validation. But there is much more! Let's start with a very basic query and try to select specific data from our `meta` field. The JSON objects in our example have two properties on the root level: "many" and "single". As of MySQL 5.7.13, we can use the `->>` accessor to specify which property we want to access. If this were a PHP object, you would call `$meta->single` to retrieve the values of the `single` property on the `$meta` object. The MySQL syntax is a bit different: ``` SELECT user_id, meta->>"$.single" FROM `things`; +---------+-------------------+ | user_id | meta->>"$.single" | +---------+-------------------+ | 100 | Towel | | 200 | Gingerbread | | 300 | Table | +---------+-------------------+ ``` If you are still on MySQL 5.7.12 or lower, instead of `->>` you should use `->`. With this accessor, all string values are quoted - for example `Towel` becomes `"Towel"`. If you wrap your expression in a `JSON_UNQUOTE()` function you can get rid of the quotes without using the `->>` operator. So far we've extracted data from the nested JSON object in our result. Using it in a WHERE condition or with an ORDER BY clause is even more interesting. In the example below, we basically search in the JSON object and limit the result to the matching condition. ``` SELECT user_id, meta FROM `things` WHERE meta->>"$.single" = 'Gingerbread'; +---------+--------------------------------------------------------------------+ | user_id | meta | +---------+--------------------------------------------------------------------+ | 200 | {"many": ["Clotted cream", "Fruit fool"], "single": "Gingerbread"} | +---------+--------------------------------------------------------------------+ ``` You can go even further using functions like `JSON_CONTAINS`, `JSON_EXTRACT` or `JSON_KEYS` to perform more advanced search or comparison operations on JSON values. Explaining all the functions would be beyond the scope of this article, but the [official documentation](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html) covers plenty of use cases. Here is just a basic example of how to use `JSON_CONTAINS()`: ``` SELECT user_id, meta FROM `things` WHERE JSON_CONTAINS(`meta`, JSON_QUOTE('Wardrobe'), '$.many'); +---------+-----------------------------------------------------------------+ | user_id | meta | +---------+-----------------------------------------------------------------+ | 300 | {"many": ["Sideboard", "Bench", "Wardrobe"], "single": "Table"} | +---------+-----------------------------------------------------------------+ ``` ## Laravel built-in support Let's be honest, who writes raw SQL these days? Most likely you rely on some kind of abstraction layer to access your database. Eloquent has supported JSON columns since Laravel 5.7, which means it translates a human readable syntax to a [grammar specific to MySQL](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php) or other database engines. With the `$casts` property on your Model you specify how you want to work with the decoded JSON in PHP. The migration below describes the table we used before: ``` id(); $table->foreignIdFor(\App\Models\User::class); $table->json('meta')->nullable(); $table->timestamps(); }); } } ``` In the `App\Models\Thing` class you define a caster for the JSON field. It's up to you if you prefer work with an associative `array` or with an `object` of stdClass: ``` 'array', ]; } ``` These are the SQL queries we used before translated to Eloquent: ``` // all things App\Models\Thing::all(); // user_id and the meta.single property $things = App\Models\Thing::select(['user_id', 'meta->single'])->get(); // all things where the meta.single property matchs 'Gingerbread' $things = App\Models\Thing::where('meta->single', 'Gingerbread')->get(); // all things where the meta.many array contains Wardrobe $things = App\Models\Thing::whereJsonContains('meta->many', 'Wardrobe')->first(); ``` To prove that the JSON encoded string is cast to an array, we can dump the `$things->meta` attribute of the last query: ``` array:2 [▼ "many" => array:3 [▼ 0 => "Sideboard", 1 => "Bench", 2 => "Wardrobe" ] "single" => "Table" ] ``` As you would expect, type casting also works the other way around. You don't need to worry about serializing or encoding to JSON before saving the data. It happens automatically since you've defined the `$casts` property in your model: ``` // read $thing = Thing::find(1); $meta = $thing->meta; // manipulate $meta['single'] = 'overwrite'; $meta['many'][] = 'or add something'; // write $thing->meta = $meta; $thing->save(); ``` ## Indexing and virtual columns MySQL doesn't have a way to index JSON documents directly, but there is an alternative: generated columns. As long as you don't use a `WHERE` condition or an `ORDER BY` clause on the JSON column, you don't need to worry about generated columns and indexing. On a very small dataset it's also not that important, but with larger datasets the right index will improve read performance a lot. To index a property within your JSON document, you first create a generated column. By default is a `VIRTUAL` column, which means values in these columns are evaluated on-the-fly and do not take up any storage. The `STORED` keyword, on the other hand, indicates that values are evaluated when rows are inserted or updated. Let's have a look at the syntax: ``` ALTER TABLE things ADD v_single VARCHAR(30) AS (meta->>"$.single") VIRTUAL; ALTER TABLE things ADD INDEX `idx_single` (v_single); ``` The expression after `AS` tells MySQL how to access the value for the generated column. The second line creates a secondary index with the name `idx_single` on the column with the name `v_single` we've just defined. The Laravel migration for altering the table with the virtual column and the index is even easier: ``` Schema::table('things', function (Blueprint $table) { $table->string('v_single', 30) ->virtualAs('meta->>"$.single"') ->index('idx_single'); }); ``` Let's have a look at the different index usage using `EXPLAIN`. Before adding the index: ``` EXPLAIN SELECT user_id, meta FROM `things` WHERE meta->>"$.single" = 'Gingerbread'; +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | things | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where | +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------------+ ``` And after adding the `idx_single` index on the generated column `v_single`: ``` EXPLAIN SELECT user_id, meta FROM `things` WHERE meta->>"$.single" = 'Gingerbread'; +----+-------------+--------+------+---------------+------------+---------+-------+------+----------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------+---------------+------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | things | ref | idx_single | idx_single | 123 | const | 1 | 100.00 | NULL | +----+-------------+--------+------+---------------+------------+---------+-------+------+----------+-------+ ``` Explanation of the `EXPLAIN`: In the first example, "Key `NULL`", "Rows `3`" and "Extra `Using where`" mean we perform a full table scan across the entire table - no index is used because there is none. For the same query, after adding the index, we see "Key `idx_single`" - the key (index) that MySQL actually decided to use - and "Rows `1`" - the number of rows MySQL thinks it has to examine to execute the query. Fewer rows means less work for the database and faster execution. ## Summary I learned a few new things in preparing this article and I hope some of you have too. Everything discussed here can be used on fortrabbit. For Apps on the Universal Stack, MySQL 5.7 has been available for a while, and recently we [introduced Mysql 8.0](https://blog.fortrabbit.com/mysql-8-now-available-for-pro-apps) support on the Professional Stack. In a follow-up article you will learn how to cast JSON fields to custom DTOs. ### Further reading elsewhere * [Arrays in MySQL 8.0 and multi-valued indexes](https://saveriomiroddi.github.io/Storage-and-indexed-access-of-denormalized-columns-arrays-on-mysql-8.0-via-multi-valued-indexes/) * [Performance Gains on JSON Column Queries using MySql Virtual Columns](https://medium.com/@michalisantoniou6/massive-performance-gains-on-json-column-queries-using-mysql-virtual-columns-and-indexes-in-laravel-dc7d289a41b3) # Dropbox as a cloud storage Source: https://blog.fortrabbit.com/new-app-cloud-storage-dropbox Created: 2015-09-04 Author: Ulrich Kautz Tags: changelog > How to use a Dropbox account as persistent cloud storage for uploads on a New App, when the local file system no longer survives a deploy. ## Using Dropbox as a static data resource for a modern PHP App We have recently written about why and how to [use AWS S3 as a cloud storage](/new-app-cloud-storage-s3) for your PHP App, especially for users of our [New Apps](/new-apps-are-here). Many have a Dropbox account. Now, you can also "misue" your Dropbox to store your Apps uploads and other static assets. The here described work-flow is quirky, we don't really recommend to use it, but we want to share with you what we have learned: ## Setup a folder with Dropbox First, you'll need to setup a public folder with Dropbox. If you don't already have a folder named `Public` on top level, please create a folder called `Public` on top level and then click [here](https://www.dropbox.com/enable_public_folder), to enable it — **quirk**. Within the public folder, create a sub-folder for your App, eg `my-app` ![](/images/01-create-folder-in-public.jpg) Once you did that, it should look like this: ![](/images/02-folder-created-in-public.jpg) Switch now into that folder, upload something (eg a random `.html` file) and copy it's public link: ![](/images/04-copy-public-link-2.jpg) It should look somthing like this: `https://dl.dropboxusercontent.com/u/123123123/my-app/some-file.html` The important part you need to remember is of course `https://dl.dropboxusercontent.com/u/123123123/my-app/` ## Setup developer credentials for Dropbox Simplified, Dropbox knows two kind of permissions: 1. Access to a dedicated _App folder_ 2. Access to everything Since you must use the `Public` folder to make your files accessible by everybody, there is no choice but to use access to everything — **major quirk**. If you're logged in, just go to the [App create page](https://www.dropbox.com/developers/apps/create): ![](/images/05-create-app.jpg) Click on _Create app_. On the next page generate you need to get your App secret (click on `Show` right to _App secret_) and must generate a new access token (click on `Generate` below _Generate access token_). The App key is not needed. That's about it for Dropbox. ## Using Flysystem to upload Now that all of that is done, let's try to read & write files with the Dropbox adapter for flysystem. You want to install `league/flysystem-dropbox`, which depends on `league/flysystem` via Composer. Following a simplistic upload handler: ```php writeStream('uploads/'.$_FILES[$uploadname]['name'], $stream); fclose($stream); ``` Of course, if you are using a framework, this will be far more elegant. Checkout [these recipes](http://flysystem.thephpleague.com/recipes/). ## Delivering files Now that's the easy part. With the public URL from above, any file you upload will be available at: `https://dl.dropboxusercontent.com/u/123123123/my-app/the-file/you-uploade.abc` Dropbox currently does not support directory listing, which is a good thing IMHO. # S3 as a cloud storage Source: https://blog.fortrabbit.com/new-app-cloud-storage-s3 Created: 2015-09-03 Author: Ulrich Kautz Tags: changelog > Set up Amazon S3 with IAM as cloud storage for a PHP app, and upload files to it from application code with Flysystem. ## Using AWS S3 as a static data resource for a modern PHP App Learn why to use a cloud storage for your Apps static files and how to set up and use AWS S3 (with IAM). Additionaly we'll show an PHP example on how to upload files from your App to S3 with flysystem. ## Why bother anyways? Everybody is talking about remote file systems lately. What the hack? Your simple web server based persistent storage did the trick all those years. PHP files are stored together with everything else — runtime data such as user uploads and [static assets](/i-love-assets). Nice and easy. Why master yet another technology? Why separate code from other data? First off, it's better: 1. **Separated**: A cloud storage mitigates the load on your application engine by separating static and dynamic requests. 2. **Scalable**: A cloud storage allows your dataset to grow and grow and grow. 3. **Affordable**: A cloud storage probably cheaper than you might think: You pay for your actual usage. With "classic" storage, you buy a volume of a finite size and pay for it, however much you might use of it. 4. **Flexible**: Data is usually the main reason why migrations are hard. Using a cloud storage from the start allows you to switch your engine (aka PHP runtime), without bothering about the data since it just stays where it is. 5. **CDN-ready** Having a cloud storage in place makes it easy to go the next step: implementing a Content Delivery Network - allowing even faster delivery of your application all around the world. 6. **Clean**: It reduces complexity by implementing the single responsibility principle. You also probably need to care. We have just released our [New Apps BETA](/new-apps-are-here). And like with other cloud providers the App storage now is "ephemeral". That means, it get's cleaned every time you deploy. You deploy with Git and you don't want to mess up your Git anyways. We are currently planning an own cloud storage solution, tightly integrated and easy to use. Until then you can: ## Use AWS S3 Simple Storage Service - or simply S3 - is part of Amazon Web Service - or simply AWS (OMG!). It's probably the most widely used cloud storage there is. It allows you to grow virtually limitless in size as well as requests/visistors. It's highly redundant and has a superb track record of availability and stability. The downside is the hard to calculate the costs and the complexity. The first thing you should now about the pricing: Don't bother about it in the beginning. If your data amount is below 10GB and you get less than a million visits per day, chances are that you end up below $10 per month. Especially while you are developing, and don't have much traffic besides your own requests, you might not even pay a few cents. ## Setup Let us guide you through it. This article will help you to: 1. Sign up for an AWS account 2. Create you first S3 bucket storage container — name space for your files 3. Set up proper permissions — safe access with additional credentials **Note**: When you first create an AWS account, there are a lot of "Get Started" and some-such links all over the place. The following guide does not mention them. Just click them away (or read them and then click them away). ### Create the AWS account If you don't already have one: Just go to http://aws.amazon.com/, click on "Sign Up" and follow the on-screen instructions. ### Create your bucket After the sign-up, you should be logged in to the AWS console - their web based dashboard. Click on services at the top, find and click on S3. ![](/images/01-go-to-s3.jpg) Now you are in the S3 console. Click on "Create Bucket". This will present you with a create dialog, in which you must decide a name and a region. Read on carefully: - The **Bucket Name** can be anything, unless it's already in use. If you choose a name in the form `sub.domain.tld`, eg `files.mydomain.com`, then you can later on route a subdomain (of the same name) to that bucket. If you don't, it's not a biggy either: You can use another AWS Service (CloudFront) later on to route arbitrary (sub)domains to your S3 buckets. Keep it simple for now. - The **Region** should be chosen wisely. If you are using any App with fortrabbit, you want to choose **Ireland** here - even if you yourself are located in the US or anywhere else. Then just click "Create" and don't bother with logging right now. ![](/images/02-choose-name-and-region.jpg) ### Configure the bucket Now that the bucket is setup it should show up in your bucket list. Click on the magnifier icon left to the name. You should now see the "Properties" tab on the right side. Open the "Static Website Hosting" sub-tab. Mind and remember the "Endpoint", which should look like `your-bucket-name.s3-website-eu-west-1.amazonaws.com`. You'll need that later. Since this article is about hosting static contents: toggle "Enable website hosting". You must insert an "Index Document". Just put in `index.html` for now and click save. ![](/images/03-setup-website-hosting.jpg) Continue with the "Permissions" tab. It's above the "Static Website Hosting" tab. Click on "Add bucket policy" and add the following. **Replace `your-bucket-name` with your actual bucket name**: ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowFromAll", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::your-bucket-name/*"] } ] } ``` Don't forget to click on "Save". ## Setup your API (upload) user Now comes the hard part. In order to upload files to your bucket from your application you need to setup access credentials. Those are named "AWS Identity and Access Management" - or short IAM. Having this said: you could skip the hard part and just use your AWS root credentials. But don't! It's a truly bad idea! So bad, that I even won't tell how to do that. ### Create an IAM User Open the top navigation, find IAM (there is a green key next to it) and proceed to the IAM dashboard. Now click on "Users" in the left navigation and then on the "Create new Users" button. Here you'll get a form in which you can create multiple users at once. Don't bother, just enter a single user name (it's just for you, so you know what is what). ![](/images/04-iam-create-user.jpg) Click on the "Create" button in the right lower corner and STOP! In this next screen, you need to copy the newly created credentials of your user: the "Access Key ID" and the "Secret Access Key". Click on "Show user credentials" then copy & paste them somewhere save. Then you can clock on the "Close button" in the lower right corner. ![](/images/05-iam-save-credentials.jpg) Halfway done. ### Create an IAM Policy You now have a user with access credentials. However, the user is not allowed to do anything. So you need to create an IAM Policy and assign it to the user. You should be in the IAM dashboard now. Click on "Policies" in the left navigation. On the right, you'll see a bunch of existing policies, with a AWS logo before them. Those are the pre-created policies of Amazon. Ignore them for now and click on the "Create Policy" button. In the next screen choose "Create Your Own Policy". ![](/images/06-create-custom-policy.jpg) Now you are in the policy create form. First the easy part: - **Policy Name**: I prefer the same name as the user name, eg `MyAppUser` or the like. - **Description**: Well, something descriptive. Strangely enough: it cannot be changed later on. Now to the **Policy Document**. Following a complete policy we recommend at the beginning: ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1440611618416", "Action": ["s3:ListAllMyBuckets"], "Effect": "Allow", "Resource": "arn:aws:s3:::*" }, { "Sid": "Stmt1440610197576", "Action": "s3:*", "Effect": "Allow", "Resource": ["arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*"] } ] } ``` Let's decrypt that: - There are two statements (rules). - The first statement is required so you can list all your buckets. Eg if you'd be using a WordPress plugin, it would probably want to present or list you all available buckets. This statements permits that. - The second statement grants all possible rights to a specific, named bucket (replace `your-bucket-name` with the name you chose) and everything "under" it. You can (should) later on limit those rights further, but especially in the beginning, a missing permission can lead to much headache! ### Attach the Policy to the User That's the last step. If you have already left the edit mode of the policy then go back there (Service > S3 Policies > Your policy). In the edit mode, find the "Attach" button and click it. You will be presented a list of all your users (and groups). Should be only one user, unless you created some on your own. Choose the above created user ("MyAppUser") and click "Attach policy". Now you are done! ## Accessing the storage If you are a Mac user, you might want to try [Cyberduck](https://cyberduck.io/) or [Transmit](https://panic.com/transmit/) to access your new bucket for the first time. For Windows users, there is there is [S3Browser](http://s3browser.com/), [CloudBerry](http://www.cloudberrylab.com/free-amazon-s3-explorer-cloudfront-IAM.aspx) and [CrossFTP](http://www.crossftp.com/). And Linux users can use [CrossFTP](http://www.crossftp.com/) as well or [CloudExplorer](https://github.com/rusher81572/cloudExplorer) (or various command line tools). ## Testing the storage To give you a short impression on how to use the newly created bucket with S3, here an example on how to upload a file using [Flysystem](https://github.com/thephpleague/flysystem). You want to install `league/flysystem-aws-s3-v3` (or `league/flysystem-aws-s3-v2`), which depends on `league/flysystem` via Composer. Then the following upload handler will work: ```php [ 'key' => 'your-iam-user-access-key', 'secret' => 'your-iam-user-secret-key' ], 'region' => 'eu-west-1', 'version' => 'latest', ]); $adapter = new AwsS3Adapter($client, "your-bucket-name"); $filesystem = new Filesystem($adapter); // upload a file $stream = fopen($_FILES[$uploadname]['tmp_name'], 'r+'); $filesystem->writeStream('uploads/'.$_FILES[$uploadname]['name'], $stream); fclose($stream); ``` Of course, if you are using a framework, this will be far more elegant. Checkout [these recipes](http://flysystem.thephpleague.com/recipes/). ## Delivering files Now that's the easy part. With the public URL from above, any file you upload will be available at: `http://your-bucket-name.s3-website-eu-west-1.amazonaws.com/the-file/you-uploade.abc`. ### Custom domains and HTTPS If you want your files available at a custom domain - or if you need HTTPS - you can use Amazons CloudFront service. To explain how to do that would go beyond the scope of this article. Here are some links, which will get you started: - [Official AWS tutorial](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html) - [Tutorial by Bryce Fisher](https://bryce.fisher-fleig.org/blog/setting-up-ssl-on-aws-cloudfront-and-s3/) # New Apps are here Source: https://blog.fortrabbit.com/new-apps-are-here Created: 2015-08-25 Author: Frank Lämmer Tags: changelog > New Apps enter beta: twice as fast at half the price, built around ephemeral storage and a rethought hosting architecture. ## New fortrabbit Apps are here (kind of) This is BETA: **Twice as fast, half the price!** Our New Apps are here. ## Vision **[Ephemeralization](https://en.wikipedia.org/wiki/Ephemeralization)** is a term coined by the visionary architect and futurist R. Buckminster Fuller: Human societies use fewer raw materials to accomplish tasks as they grow more advanced. So it's basically about doing more with less through technology. We took this literally — so our new generation of Apps needs less hardware resources, uses ephemeral storage and is less expensive. ## Evolution The initial fortrabbit platform launched in 2012 — [3 years ago](/take-off-fortrabbit-php-platform-launched). The “PHP renaissance” motivated us to build a hosting platform for a new PHP mindset. “Encourage, not enforce best practices” was the motto, thus legacy support was important to us. So we developed a very unique cloud hosting solution which offered Git push to deploy and native Composer integration aside basic LAMP features like SSH access. Now, the PHP community is moving on. Tools are evolving. Deployment habits are changing, Git is superseding FTP. Modern frameworks/CMS are now based on Composer packages and support file system abstraction. Performance is becoming an even more important factor. Developers know how to use alternative session handlers and cache drivers. They want a hosting that scales out horizontally. Most hosting solutions like VPS or shared hosting can't handle this. We think it's time now to abandon some old habits in favor for more advanced technology with a higher performance at a better price. > Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. — Antoine de Saint-Exupery ## What's in it for you We believe that your creativity and PHP skills, a modern framework and the fortrabbit hosting platform are an awesome combination. This new generation of Apps increases your productivity while in development and scales even better in production. The more affordable pricing is better suited for experiments, weekend hacks, pet projects or any kind of small website. ### Faster delivery Quick delivery is a core of our service and the backbone to success of any App. #### Old persistent storage Old Apps are featuring SSH & SFTP access and a persistent storage for the App to write runtime data. This is implemented through a network attached storage, shared by all services. Though very convenient, the bound is I/O with only moderate speed in read/write operations on the file system.. #### New ephemeral storage New Apps don't need SSH/SFTP. The transitory storage permits persistent runtime but provides far superior I/O as it is implemented locally on SSD. In addition, horizontally scaled Apps (all production plans) will leverage a multiplication effect: Each Node the App runs on comes with it's own storage and thereby multiplies the I/O available to the App. #### HTTP response time | Framework/CMS | Old App | New App | | ----------------------------------------- | ------: | ------: | | Lumen 5.1 vanilla (welcome route) | 90ms | 35ms | | Symfony 2.7 demo application (blog index) | 200ms | 70ms | | Drupal 8 beta 13 (home route, cached) | 260ms | 60ms | | Wordpress 4.3 (blog index) | 310ms | 135ms | That's the total time until a response from a single request is delivered to the browser, including PHP execution time and network latency. Measured with [webpagetest.org](http://webpagetest.org) (same AWS region, repeated view). #### PHP execution time | Framework/CMS | Old App | New App | | ---------------------------------------- | ------: | ------: | | Lumen 5.1 vanilla (welcome route) | 70ms | 3ms | | Symfony 2.7 demo application(blog index) | 165ms | 34ms | | Drupal 8 beta 13 (home route, cached) | 210ms | 25ms | | Wordpress 4.3 (blog index) | 260ms | 115ms | That's the pure time PHP took to deliver a result. Measured with Blackfire Profiler (10 samples). ### Atomic deployments A fast and convenient Git deployment with Composer integration is a core of the platform. We have re-engineered and much improved for New Apps: #### Old App rsync deployment You Git push to your fortrabbit remote repo. A rsync tasks synchronizes the changes to the shared web storage. Individual files are getting changed incrementally, one by one then Composer and the other optional scripts are executed. This Old Apps deployment is very fast and runs mostly without downtime. But it didn't met our stability standards in the long run. #### New App atomic deployment You Git push to your fortrabbit remote repo. In a build process Composer and other optional deploy-scripts run. During release everything get's packed and uploaded to temporary space. From there the release package get's distributed to all Nodes the App runs on. With a graceful service restart the new, complete code base will be used — all at once. The New Apps deployment is about as fast as it's predecessor model and is also nearly downtime less. The new integrity checks make sure all steps have run successfully and only a consistent state is distributed. ### Better process handling The pricing structure has been optimized to make it easier to understand, more transparent and also to offer more options. The PHP power of Old Apps is measured in a unique unit called Processes. The New Apps are more containerized and simply use dedicated PHP memory as the main unit for vertical PHP scaling. In higher scaling plans you can even adjust the number of processes you would like to run within the given RAM. ### Better PHP scaling Fine-grained options to scale PHP matching more use cases. The Old Apps offered a linear model to scale PHP. Each PHP scaling plan doubled the PHP power (vertically) and the number of Nodes (horizontally). New Apps can independently be scaled up (vertically) and scaled out (horizontally). Add more RAM (vertically) to meet the requirements of your App, increase the number of Nodes (horizontally) to serve more requests. ### More general stability We are proud of a good uptime track record for over the past years. The new infrastructure helps us to maintain and even rise this level of reliability: it is build upon an incredibly fast network messaging system, which transfers configuration changes, code deployments and system health states within milliseconds. The switch to the ephemeral storage allowed us to reduce the App setup complexity leading to a better, more stable and faster reacting infrastructure. ### Massive price cut “Your platform is sooo cool, i wish it would be more affordable.” This kind of feedback is what we get most frequently. And it's true, we see a lot of low traffic Apps around. The new architecture enables us to reduce expenses and reduce the price by 50% for the entry level scaling. This opens up the range of use-cases for you: - Old App starts at **10€** - New App starts at **5€** ## Beta facts Software is never ready. We want feedback quickly. Here is the first iteration of our new product line. It's not as complete as the Old Apps, so it wears a Beta-badge and it is running aside of the Old “classical” Apps. ### Scope Test it, use it for staging and even for small projects. For now, you will have the choice between Old and New for every App you create. As long as the Beta does not include most scaling options, we advise not to host mission critical applications here yet. The old classic Apps are still a good choice for that. ### Limits There is only one small scaling preset for tinkering and not all components are available yet. ### Availability The Beta is public and not limited in availability or time. The infrastructure has been intensively stressed. But there is no test like production — this beta period is the final fire test. We are very confident of stability so we guarantee our standard uptime of 99%. ### Pricing The new more affordable pricing will stay and might even go down — it is not some shady for introductory offering. We believe that this opens up the service for more different applications. So we are very curious to see what you do with it and what you think about it. ### Beta timeline We don't rush things. It's going to be ready when it's ready. During the next months we will make scaling and additional components available. When feature complete the New Apps will become default. Existing Old Apps won't be turned off anytime soon — we plan to support old Apps for at least until mid 2016. Important changes will be communicated upfront. ### Migrating from Old to New Due to the architectural differences we can't offer automatic transfer from Old Apps to New Apps. You need to do that manually. We will publish detailed informations soon. We will also offer individual hands-on migration service for Apps in production later on when leaving Beta. We are going to help as much as we can. ### Current comparison table | Feature | Old App | New App | | -------------------- | ---------- | --------- | | deployment | rsync | atomic | | storage | persistent | ephemeral | | disk I/O performance | low | high | | http performance | moderate | high | | MySQL performance | moderate | high | | min scaling price | €10 | €5 | | horizontal scalable | yes | soon | | MySQL | yes | yes | | SSH/SFTP | yes | no | | PHP7 | no | soon | | Metrics | yes | yes | | SSL | yes | soon | | Workers | yes | soon | | Memcache | yes | soon | | Asset storage | no | soonish | ## Bottom line The New Apps rock (we think at least). The new tiny PHP scalings with only 32 MB memory performed very well in our tests. While a lot will look and feel very familiar, another lot will change. The way the file system works in the new architecture is significantly different. It's a good opportunity to learn a few new tricks now. See the [help article about New Apps](http://help.fortrabbit.com/old-and-new-apps). # Announcing GA for New Apps Source: https://blog.fortrabbit.com/new-apps-ga Created: 2015-12-10 Author: Frank Lämmer Tags: changelog > New Apps reach general availability, more scalable and extensible than the beta, and the platform update that got them there. ## A big update

It took us longer than anticipated, but finally — here we go again — with yet another big platform update this year.

Back in [August](/new-apps-are-here) we have launched a BETA of our new generation of Apps. Thanks for all your feedback! The number question was: When can i use it in production? Well, now you can. ## Updates at a glance - [General availability](#toc-new-apps-ga) for New Apps - New Apps can be scaled now: PHP, MySQL and Memcache - [New pricing/performance](#toc-new-pricing): more power, more affordable, better matching - [Improved documentation](#toc-documentation) - [All new design](#toc-design) - [Vanity App URLs](#toc-vanity-urls): "appname.frb.io" - [App Secrets](#toc-app-secrets): store confidential data safely - [New TLS](#toc-tls): more affordable https for custom domains - [New metrics](#toc-metrics): Memory usage, Swap usage **This platform update is non-destructive. Everything you have set and booked now will exactly stay the same.** There are just some nice new features and options.

New Apps

We are indeed very happy with the [New Apps](http://help.fortrabbit.com/new-apps). They have proven to be stable. Due to the new architecture nearly all aspects are [much faster](/new-apps-are-here#metrics) than their [predecessors](http://help.fortrabbit.com/old-apps). Now, with Memcache and additional PHP scaling plans with high availability options, you can use them finally in production. "New Apps" are now simply called "Apps". Old Apps are still available, you can even book new Old Apps within the Dashboard. But please mind that Old Apps are in the sunset phase — end of life is planned for mid 2016. Don't worry now about migration too much now. We will post more informations soon.

Pricing

The whole service palette has been updated and new presets help you to get started. You can now enjoy the benefits of a production scaling during the "free trial"! The Component sections are more descriptive. There is a **[new specs page](https://www.fortrabbit.com/old-platform/specs-uni)** with all techy details and limits on plans. With the New Apps we switch from amount of PHP processes to amount of available memory as the distinctive feature for PHP plans.

Price changes

The price-performance ratio generally has changed for the better: The same resources have become more affordable or a comparable plan has become (much) more powerful. The whole new infrastructure is **now a 100% powered by SSD hard disks** and running on the latest hardware. **All new prices are fully opt in, you can choose the New Apps and the new plans but you don't have to. If you do not, you keep your currently selected plans.** Resources for the PHP plans have mostly become more affordable and in all cases more capable. Direct comparison with the Old Apps is not possible, as the whole structure is so different. We plan to write a more detailed decision making guide when migrating from Old to New, in the meanwhile please check out the [technical changes](http://help.fortrabbit.com/new-apps) to get started. New MySQL plans are more powerful than the old ones, our testings showed up to 2.5 times faster responses. #### Price reductions | Plan old / new | Old App price | New App price | | ------------------- | ------------: | ------------: | | SSL dedicated / TLS | €20 | €5 | | Memcache s | €15 | €10 | | Memcache m | €30 | €20 | | Memcache l | €60 | €40 |

Two dimensional scaling: vertical + horizontal

The new pricing model allows to scale in two dimensions. Scale up vertically to increment memory to match your Apps requirements, [also see here](http://help.fortrabbit.com/). Scale out horizontally to increase the number of PHP requests your App can handle.

New single Node plans

We have three new PHP scaling extension states within the Tinkering section: "PHP s 1" with 128 MB, "PHP m 1" with 256 MB, "PHP l 1" with 512 MB. The container sizes matches the production plans. So you can run your App on a single Node plan and only have to upgrade to production whenever you think, you are ready.

No "PHP xxs" & "PHP xs" for new Apps any more

The "New App BETA" was available in two extension states: the initial "PHP xxs" with 32 MB of memory and "PHP xs" with 64 MB. Those tiny sizes were astonishingly capable, but lots of frameworks and CMS require more RAM once you start actually using them. The New Apps in BETA started at €5 with 32 MB (including MySQL), the now final New Apps are starting at €7 and with 128 MB (including MySQL). You will not be forced to update: Currently booked "PHP xxs" & "PHP xs" plans will stay booked. We are still discussing the "PHP xs" scaling. I personally really like the idea, of a tiny container for smart hackers and micro frameworks — Do more with less. Your feedback is very welcome!

Dedicated PHP plans

The platform is getting even better for our "power users" with the dedicated PHP scaling level. They grant real power (running on dedicated Nodes) and more control: the amount of PHP processes is changeable.

Vanity App URLs

We have a funky new shorter scheme for all New Apps. Instead of `my-app.eu2.frbit.net` you can now use the shorter version `my-app.frb.io`. The new scheme is the new standard, but the old URLs will stay valid, so you don't need to update your CNAME records. Old Apps keep the `old-appname.eu1.frbit.net` URL scheme for now.

TLS

"HTTPS everywhere" is definitely a trend. Our new TLS component is dramatically more affordable and based on a new technology: In the old implementation we had to reserve a dedicated load balancing Node for each SSL certificate. Thanks to the newer TLS with SNI, we can we can now implement multiple certs on a single Node. Please mind that SNI based HTTPS will not work in some really, really old browsers (IE6). The new TLS is still a "bring your own certificate" solution (you need to purchase it from a 3rd party). We are aware of the new free certs from Let's encrypt and are considering this as a future feature. Please also read our [recent post](/httpspeedy) about this.

App secrets

![Secrets in the Dashboard](/images/secrets-preview.png) A while ago we kicked off a [discussion](/how-to-keep-a-secret) on the (bad) practice of storing secret informations in ENV vars. Now, we introduce a new feature called App secrets to help you keep your App secure. The `secrets.json` is a file in your App. Only you and your team have access. It's a vault for secrets provided by us — think: database password, plus your own sensitive informations - think: API keys, passwords and so on. Parsing secrets is easy. The App secrets are an optional new feature only for New Apps. - [App secrets help article](http://help.fortrabbit.com/app-secrets)

Metrics

We have new metrics: Memory usage shows you how much RAM your PHP actually needs. Swap usage informs you when the PHP memory exceeds and the hard disks is used to perform calculations (ouch).

Design updates

![New and old design compared](/images/old-new-design-01.png) Separating presentation from content is a nice idea. In reality both fields often blend. Design is how it works (and how it looks). Design is about communication. Here are the most notable improvements: - All fortrabbit properties (www, blog, help, dashboard) have a new look. - Forms are more beautiful now (label-input-groups). - More visual hierarchy. - More contrast. - It requires less clicks to get somewhere. - The design is more desktop friendly — dense. - A more descriptive pricing/booking and scaling flow. - New access pages (Git, MySQL, SSH, logs) with practical code examples. - ENV vars are editable all together in dotenv format now. - SSH keys now include the added date for better identification. - All SSH keys have a beautiful visualization now. - Certain actions in the activity stream can now be unfolded to show details. - Lists (Companies, Users, Apps, Activities) can be filtered. - More copy/paste friendly inputs for code examples. - Even more "Daily developer quotes" on Dashboard, author is separated. - Companies have nice little first-letter icons now. - Company access roles for Users are easier to understand now. - TLS common name is matched against domains. - Favicons are shown to help identify domains. - All views have been reviewed and re-texted for better understanding.

Documentation

We have put some efforts to get the help pages up-to-date. All articles now reflect the features-set of the New Apps, articles for Old Apps are still available. ### New & updated articles - [About New Apps](http://help.fortrabbit.com/new-apps) ‹ What changes in contrast to Old Apps - [About Old Apps](http://help.fortrabbit.com/old-apps) ‹ Resources for still working with Old Apps - [Install Grav](http://help.fortrabbit.com/install-grav) ‹ New tutorial for a new CMS - [Install Slim 3](http://help.fortrabbit.com/install-slim) ‹ New tutorial for the just released Slim framework - [Scale PHP](http://help.fortrabbit.com/php-scaling) ‹ Everything you need to know when scaling PHP ## Other changes This updates includes a huge number of small bug fixes, improvements, some small details have also been removed. The security settings give you some more control, sessions are stored correctly now. Our marketing website www.fortrabbit.com has been improved to explain our services even better. This blog is now powered by PHP, before we had a static site generator. ## Mission statement Our aim is to build the perfect PHP platform. fortrabbit is not a playground to try out the latest bleeding edge technology. It's a solid hosting solution for your applications in production. It implements best modern practices. We subscribe to long term thinking and developer happiness. You get more out of it, the more you use it. Long-term love instead of short-term buzz. ### Release status We tried to find the right balance between "release early" and "release stable". So we expect this update to be solid, we have tested it thoroughly. But it might be rough around some edges. Please report if you find something to be broken. ## Future roadmap The next updates are already in the pipeline. The New Apps are basically ready now, but there are still two Components missing to make them fully feature complete: **Workers** Many modern web applications require background and cron tasks. We are working on a new solution for New Apps. **Asset storage**: New Apps have incredible fast local ephemeral storage. Unfortunately you can not store runtime data there, as everything will get wiped on each deployment. So we are working on a cloud storage solution to make the New Apps even more complete. Until then please use an external provider, such as AWS S3, for this. Apart from that, we will of course introduce **PHP7 soon**. We are also preparing to expand our service to the United States, with a new data center location and prices in USD. We are considering a new trial model to try out our service and interactive tutorials to explore platform features. # New features at fortrabbit Source: https://blog.fortrabbit.com/new-at-fortrabbit-2022-04 Created: 2022-04-04 Author: Frank Lämmer Tags: changelog > A recap of recent platform work: a basic web application firewall setting, Craft Copy for Nitro, and Craft Copy for Craft CMS 4. ## Basic WAF rules There is a new setting in our Dashboard to enable a basic Web Application Firewall. This will block common routes that are often targeted by bad bots to scan your App for vulnerabilities. While those routes often don't exist (since these attacks mostly target WordPress), the requests still often create load for the PHP runtime. The new WAF rules feature will block access before the requests reach your App. This feature is now enabled for all new Apps when they are created. We advise all existing App owners to turn this on for all kinds of Apps. Continue reading on the [WAF help page](https://help.fortrabbit.com/waf-rules). ## Craft Copy for Craft Nitro Our Craft CMS deployment tool Craft Copy now supports Craft Nitro, the popular local development tooling based on Docker. There is an additional wrapper script to enable missing binaries within your Craft Nitro container. Continue reading on the [Craft Copy help page](https://github.com/fortrabbit/craft-copy#craft-nitro-support). ## Craft Copy BETA for Craft CMS 4 BETA There is a [craft4 branch](https://github.com/fortrabbit/craft-copy/tree/feature/craft4) with Craft Copy to test Craft Copy with the newest version of Craft CMS 4 (both currently in beta). ```shell composer require fortrabbit/craft-copy:craft4 ``` ## Restructured help pages The [help pages start page](https://help.fortrabbit.com/) has been reorganized, making it more accessible and easier to scan quickly. The sections are now domain specific, so under the MySQL headline you will find all the articles, from connecting to troubleshooting. A new version of Algolia search is now also available. We are still tweaking the search results here and there. ## Git `main` branch support We now finally support the `main` branch with Git deployment. That means whenever you push to fortrabbit: `main`, `master` and `{app-name}` will all be deployed into the App space. Check the [details with our help pages](https://help.fortrabbit.com/git-deployment#toc-the-branch-name-that-counts). ## PHP 8.1 and PHP 7.3 EOL PHP 8.1 was introduced. We are about to switch the last remaining PHP 7.3 Apps to PHP 7.4. Please mind that PHP 7.4 will reach its end of life by the end of this year. ## Phalcon4 support for PHP 7.4 We have now also included the Phalcon4 extension for PHP 7.4. Our plan is still to drop the Phalcon extension. We are looking forward to Phalcon 6 to be available as native PHP via composer. See the [Phalcon developers roadmap](https://blog.phalcon.io/post/phalcon-roadmap#v6). ## MySQL query time limit MySQL queries should not run for ever. That's why long running MySQL queries will be killed after some time now. The current limit is 1 hour. We are still experimenting with the best timing. This will help some Apps from getting stuck in endless loops. ## Object Storage driver updated for Laravel 9 Our easy peasy [Laravel Object Storage driver](https://github.com/fortrabbit/laravel-object-storage) is now on version 2. It is compatible with Laravel 9 and Flysystem 3. ## Looking ahead We are currently defining and designing bigger platform updates. This project will still take a lot of time, but we are making progress. Updates on that project to follow. # A new blog layout, a new engine Source: https://blog.fortrabbit.com/new-blog-layout Created: 2015-01-23 Author: Frank Lämmer Tags: chronicles > A new blog layout on a new engine, and why a static site generator replaced WordPress for a developer-facing company blog. ## New blog same old bla bla We have a new blog layout. It's streamlined with the rest of our new identity. I hope you like it. ### WordPress is not for modern devs Well, WordPress is very very hackable. You can do almost everything with it. And whatever you need: it has been done, documented and open-sourced before. Wordpress is feature-rich and extensible. The WordPress admin is perfect for non techies (speak clients). We want: Markdown, version control, minimalism and edginess. ### Evaluating alternatives Obviously i was interested in a modern Laravel blogging engine. I tried out [OctoberCMS](https://octobercms.com/) and [Wardrobe](http://wardrobecms.com/). While they are great — my playfulness wasn't satisfied yet. ### Static site generators So i digged into static site generators — those systems that spit out a bunch of HTML pages. Of course I first checked out the PHP ones [Sculpin](https://sculpin.io/) and [Phrozn](http://phrozn.info/en/). Then i moved on to Node.js generators as I already use [Gulp](http://gulpjs.com/). I finally settled with [Metalsmith](http://www.metalsmith.io/). It's not newest hippest technology — but ok for me. ### Learnings - Write cleaner code! - Open source code for pull requests - Gulp & Metalsmith live side by side — not good - Generation is quick, but an additional step - Reinvent the wheel for all details (RSS, 404 …) - Exclude "build" from Git - Figure out a deployment process to fortrabbit # New dashboard migration guide Source: https://blog.fortrabbit.com/new-dashboard-migration-guide Created: 2014-10-15 Author: Frank Lämmer Tags: chronicles > What actually changes for existing customers when the new fortrabbit dashboard arrives, including the move from freemium to a free trial. ## Boarding the new dashboard **tl;dr** The new dashboard is coming. It's going to be phpantastic. No action required from your side (most likely). Our [last article](/mission-statement-the-new-dashboard) praised the new features this article explains changes. ## Freemium to free trial **DISCLAIMER**: Don't be scared. We are (still) the good guys. This is not a shady subscription trap. Everything is opt-in. You can cancel at any time. You will not have to pay a cent more. We are finally going to fix this free App slot thing; those nasty freezes. As [announced](/sunsetting-freemium) we are going to introduce a timely limited free offer instead of a free-forever model. You can still create free test/trial Apps to evaluate our service. Free test Apps will now be removed (killed) — not frozen — when their time is up. You can always start a test/trial App: No more waiting slots! The testing period is (most likely) 72 hours, but you can ask us to extend it as long as you think you'll need. Here is what happens when we switch: Your running free Apps will be automagically converted to trial Apps. Your already frozen (free) Apps will no longer be available. Yes, wee are going to delete tens of thousands of neglected "you have arrived" test Apps. #### How to backup currently frozen Apps Do you have any frozen App that is important to you? Make sure you grab everything now. 1. **See it again**: unfreeze your App in the dashboard 2. **Get code**: since you are using Git (you are, aren't you?): you most likely have a local copy of the code already. If not login via SSH/SFTP and download or git pull everything 3. **Get database**: if you have a MySQL database, connect to the database (via SSH tunnel) and export the database ## Git/SSH/SFTP workflow changes Managing your public SSH keys for Git & SSH access becomes less of a pain: After the switch, you can manage your SSH keys centrally — with your Account.. and they'll be added to all the Apps you have access to. Also the keys will be installed to your all your Apps' SSH/SFTP accounts as well (though all manually installed SSH keys will be kept as well). Of course, App-only SSH keys will still be possible, so you can safely integrate with 3rd party services which you don't want to grant access to everything you own. During the migration we will do our best to your SSH key to your Account. But better safe than sorry: If we cannot definitely associate an SSH key with an Account, we will keep it as App-only. So no Git/SSH/SFTP accesses will be added nor removed. As for password authentication for SSH/SFTP: Still possible and all existing passwords will be kept. However, you can now switch it off (which is the default for new Apps) at any time. Keep in mind: Our new Git-mostly "Ephemeral Apps" are also going to come soon (and they are going to be great). ## Teamwork changes We are revamping our "permission management". It's going to be lovely. I have written about the backgrounds of the new multi client model [here](https://medium.com/@frank_laemmer/our-multi-client-model-3b965d2f1060). So how will it look? There are going to be "Owners" and "Admins". These will grant you access to a Company, which in turn owns Apps which you then can access. Also there will be a "Developer" role (which also belongs to a Company): it grants you access to only a subset of the Apps of a Company. Sounds a bit complicated? Nah. "Progressive disclosure" will help, you will find all the advanced features when you need them. This happens after the switch: The "Analyst" role (let's say: sparsely used) will be removed. We will convert the current "Junior Developer", "Lead Developer" and "Project Manager" to the new "Developer" role and grant them access to all the Apps they can access right now. This implies some downgrades: "Developers" cannot scale nor remove an App. ## Product structure changes The new structure will be more modular and will smooth the way for the upcoming Ephemeral Apps. Here is how it goes: We are splitting the current App into three separate products: The App (a base container, if you will), the scalable PHP product and a scalable MySQL product. Don't panic: The price is going to be exactly the same. The great thing about it: It will allow us to offer far cheaper Apps in the future. On that note: we are also changing our whole invoicing system. You will have an invoice archive where you can download previous invoices and suchlike. ## Only CNAME routed domains Your old naked domain routing A-Records will still work. But we will not communicate A-Record IP addresses routing any more. Naked domains are visually more appealing and easier to set up, but they come with huge disadvantage that we can't move your App quickly in case of emergency. We already stopped communicating A-Record endpoints. ## Timeline It's going to be ready when it's ready. We hopefully will switch happen later this year, November or **December**. ### The switch We'll expect a little downtime for our dashboard during switch. As far as we see now, your Apps will not be affected. Maybe the invoices will be delayed. ### Communication We gathered all changes here. We will update this page when, something else will come up. You will be informed about the exact date at least a week beforehand. # New dashboard supervision Source: https://blog.fortrabbit.com/new-dashboard-supervision Created: 2015-03-04 Author: Frank Lämmer Tags: chronicles > Releasing a dashboard that took years to write, then watching how it lands. On feedback, missing features and shipping big projects. > Release early, release often That's what they say. We on the other hand have just released a big fat bunch of code — our new Dashboard — which took us ages to write. Launching a big project to public is always hard. Software is never done. The list of features which didn't make into the release is long. We did testing, but have we really covered every possible case? Can we really let go now? Shouldn't we reach 100% test coverage? Or should we release it with a BETA badge now? > There is no test like production We did it. We shipped it. It's here. It's as good as it got. It's stable. It's rough around the edges. We are tweaking it right now. **Thank you for your feedback!** We could eliminate many smaller glitches already. ## Your opinion counts! The new fortrabbit Dashboard is full of assumptions. What do you think about it? Do you like it? What are you missing? Where are you lost? What's not working as expected? Which feature from the old Dashboard would you like to see again? Have you found a bug? What do you think about our new support model? How do you like our new trial model for Apps? Post a public comment right below or use our [client feedback form](https://dashboard.fortrabbit.com/support/ticket?type=sales) for a private conversation. We are listening. # App collaboration & owner transfer Source: https://blog.fortrabbit.com/new-features-app-collaboration-transfer Created: 2012-12-18 Author: Frank Lämmer Tags: chronicles, changelog > Permission management arrives: app collaboration for teammates, owner transfer, and the multi-tenancy workflows that come with it. We are thrilled to announce the availability of a new feature from our roadmap: [Permission Management](http://fortrabbit.com/feature/permission-management). Actually these are two three (maybe even four) new features for the web control panel: ## App Collaboration Grant your team mates access to your App - multi-tenancy workflows for the web control panel. Set the level of permissions based on roles: * **Analyst:** read only * **Junior Developer:** change settings * **Lead Developer:** change settings, scale App, purchase Add-Ons * **Project Manager:** change settings, scale App, purchase Add-Ons, handle collaborators * **Owner:** change settings, scale App, purchase Add-Ons, handle collaborators, delete the App Sorry, this new feature is only available for paid plans. It was simply easier to implement like this. #### Who Benefits? We really like this feature, because it's not yet another tech feature, it solves a real world problem between people. It helps anyone who has to manage multiple Apps with different co-workers and maybe even different owners. It's a good solution for **dev shops** and **web agencies**. ## App Transfer Change the payee of an App by inviting a new owner. The new owner will be guided thru the boarding process. After the transfer you can still work as a collaborator on the App - of course, when both parties agree. #### Who Benefits? Again this helps to manage your real world hosting needs. Imagine this workflow for you as a **freelancer:** 1. develop a project for a client (maybe on a free plan) 2. send over testing URL 3. get feedback 4. implement changes, send over for review again (loop steps 3 & 4 a few times) 5. get approval from the client 6. invite the client to take over App ownership 7. the client becomes fortrabbit client 8. you are still the project manager and can handle the App for the client 9. you launch the app for the client (scale and route domain) ## App History Each App has an event log now in the web control panel. Here you can see exactly who changed what and when. #### (4) Bonus feature: Gravatar support Ok. That's really a minor change and not really worth mentioning: Now you will find icons on your profile and anywhere accounts need to identified in control panel. These profile icons come from the free [Gravatar](http://gravatar.com) service. So in order you want to see your beautiful face up there you need to have your e-mail registered on Gravatar. We have noticed that a lot of our users are already using this anyways. # New fortrabbit.com teaser page Source: https://blog.fortrabbit.com/new-fortrabbit-com-teaser-page Created: 2012-06-21 Author: Frank Lämmer Tags: chronicles > A coming-soon page for fortrabbit.com with an HTML5 video background, and a survey asking developers what the platform should be. **Why Don't we do it in the Cloud?** We have just launched a new coming soon page on our upcoming main domain: [fortrabbit.com](http://fortrabbit.com). **Frontend Geek Talk: **I have played a bit with HTML5 Video in the background. Moving clouds to visualize the dynamism. Looks best in WebKit based Browsers. It's not consuming as much CPU as flash video would do. **Credits:** [JQuery Video Background](https://github.com/georgepaterson/jquery-videobackground) plugin by George Paterson (slighty hacked). Cloud Timelapse Video by [orangeHD](http://www.orangehd.com).** ** ### Help us understand your needs! We have also set up [this small survey](https://www.survs.com/survey/87GEQWBQ4Q) where we ask you 20 questions about your preferences on hosting and development. You can really help us a lot building a better product by filling it out. Please also fill out the survey when you are interested in a private BETA of our product. # New platform public BETA Source: https://blog.fortrabbit.com/new-platform-beta Created: 2025-11-26 10:24:14 Author: Frank Lämmer Tags: changelog, chronicles > The new fortrabbit platform opens in public beta after years of work — a hosting service rebuilt from scratch rather than updated. It's been years in the making: thousands of tickets, countless cups of coffee, endless debates about tiny details. Now we are finally ready. This is not just another update. We built something entirely new from scratch. We **completely redefined** our optimal vision of PHP hosting. It's a big bet. Fingers crossed you like it. 🤞 ## What is fortrabbit anyhow? Inspired by the original Heroku PaaS: a hosting platform to deploy modern PHP websites and web applications. It's apps, not servers; it integrates GitHub, runs on AWS, and won't break your bank. It encourages best practices, but doesn't judge you when you ignore them. It's a good fit for modern PHP-based websites and web applications built with Craft CMS, Kirby, Statamic, Laravel, Symfony, and many more. - **Intuitive dashboard** that gets out of your way - **Persistent storage** with direct SSH/SFTP access - **Component based pricing** to individually book and scale parts - **Workers** offload tasks to the background - **Free trial** available for each new app - **Transparent pricing** with component-based model - **No setup fees** or hidden costs - **Pay-as-you-scale** philosophy - **GitHub signup** - **Connect any GitHub repository** git push to deploy - **Build pipeline** with Node.js support during deployment - **Multi-environment staging** with branch-based environments - **SSH key-only authentication** for better security - **Key-value store** (coming soon) ## Why a BETA for a hosting service? I've written about our [decision to do a big rewrite](/yes-we-rewrite) before. We needed a complete overhaul. We've been working on the new platform for years. It became our home and we quite like it. It's time now. While we are still polishing some edges and adding features, the core experience are ready. :ContentQuote{text='There is no test like production.'} Opening it up is exciting, but also a bit scary. We are stepping out of our comfort zone to see how you interact with the platform. It's already a significant upgrade over the old platform. It's ready for action. - **Now open to everyone** - It's paid. We are confident in the value it provides. - [See all BETA details](https://docs.fortrabbit.com/platform/new/beta) ## New design Building on the existing brand, the design language got an update. We still use the old logo; colors and typography have been refreshed. We hope you like. You are looking at it now. [Goodbye old design](/goodbye-hello). ## Updated web properties Our websites have been updated. Communication is mostly about the new platform. But the old platform is not going anywhere soon. Both systems will run [side by side](#no-rush-for-existing-clients) for a long time. ### New platform access - [dash.fortrabbit.com](https://dash.fortrabbit.com) - new dashboard - [docs.fortrabbit.com](https://docs.fortrabbit.com) - new docs - [www.fortrabbit.com](https://www.fortrabbit.com) - new marketing (replaced old) - [blog.fortrabbit.com](https://blog.fortrabbit.com) - new blog (replaced old) ### Old platform access (unchanged) Existing customers can still continue to use the old system as usual. See [new and old side by side](#no-rush-for-existing-clients). - [dashboard.fortrabbit.com](https://dashboard.fortrabbit.com) - old dashboard - [help.fortrabbit.com](https://help.fortrabbit.com) - old help ## New pricing When the service was launched 13 years ago, our vision was to raise awareness among developers that hosting is not just about getting more horsepower per dollar. Our aim was — and still is — to create an understanding of the value of a managed hosting service. It's not the cheapest service, but if you are using it professionally, you can easily afford it. That turned out to be a tough sell. Web hosting is still mostly considered a commodity. We also saw the understandable wish from developers to host many small websites, like: - Fun, personal, weekend projects - Small client projects - Staging environments Unlike with a VPS, where you have one server to cram with your projects, fortrabbit uses dedicated resources for each environment. This is, we believe, the better but also more expensive route. So, one of the design goals was to come up with more affordable pricing. It was also a requirement to create an entirely new platform. A Herculean task against all odds. So much of a product is pricing. ### Infrastructure I am very proud of the work the infrastructure team has done in this area. We have been able to cut down our reliance on AWS, enabling us to revisit the infrastructure provider question later. For now, we found creative ways (and hacks) to keep AWS costs low. - More intelligent allocation and redistribution - Better resource utilization ### Pricing structure We also looked at pricing from the product view. The old platform has three easy-to-understand plans. While this helps with cognitive load, it's also wasteful. We adapted the component pricing of the former Pro Stack for the new platform. - XS plans: little resources, but affordable - Component-based: pay only for tech you need - Easy scaling: pay only for resources you need To make things easier, we included different pricing presets for software. When booking a flat-file system that does not require a database (Kirby, Statamic, Grav …), the MySQL component is not pre-selected. When booking software that requires more resources, we suggest that right away. In addition, there are [pricing examples](https://www.fortrabbit.com/pricing#examples) showcasing use cases with multiple environments. We also removed the old company plans because they often confused customers. ### Pricing state In total, you'll get much more performance for the same price with the new platform, and there are also additional smaller plans. This will enable many more interesting use cases. We are curious to see how the new pricing will be perceived, specifically the component based pricing is a bet. See our new [cost breakdown](https://www.fortrabbit.com/us/cost-breakdown) to get an idea about our spending. ### Pricing outlook We still need to gather more experience with performance running more environments. So pricing is also subject to change. ## New docs We take customer education and self-service seriously: there are now about 300 articles with a total of ~80,000 words and ~560,000 characters. It's based on the current help pages but significantly updated. You don't need to read it all to get the platform. It's just there. The documentation is human-written (with some help from AI), well-structured, curated, and maintained. It's easily accessible, searchable, and designed to be easy to read and parse. It's also well-linked from the new dashboard: The little `[i]` icons provide inline help as well as links to relevant articles. ## New legal section We have reviewed and extended our legal center. The new legal docs are applicable for all existing and new customers, covering the old and the new platform. The updates are done for clarify. - [fortrabbit.com/legal](https://www.fortrabbit.com/legal) - New legal center - [github.com/fortrabbit/legal](https://github.com/fortrabbit/legal) - Legal docs with full changelog ## No rush for existing clients The old platform continues to run in parallel, giving you plenty of time. We'll support you hands-on with the migration when you are ready. - **Side-by-side operation** - both platforms will run in parallel - **Self-service migration** for early adopters - **Assisted migration program** planned for later - [New and old](https://docs.fortrabbit.com/platform/new/new-and-old): side by side - [Changes](https://docs.fortrabbit.com/platform/new/changes): old and new platform compared - [Migration](https://docs.fortrabbit.com/platform/new/migration): timing and details ## What's next? This BETA launch is just the beginning. We've got a full backlog. Next, we are working to make it feature-complete and even more robust by hosting more production websites and web applications. From that list: - Live server metrics in the dashboard - Live logging in the dashboard - Live event log in the dashboard - Event notification system - Extended collaboration - Key-value store It will take a while until everything will come available. The next step is general availabilty. As usual, we are conservative about timing, we look forward to remove the BETA flag in 2026. ### PHP 8.5(.1) We are preparing for PHP 8.5 and will roll it out as soon as all supported extensions are updated and tested. We want to ensure a smooth transition, so we'll likely release it with the first dot version. ## We want your feedback Don't just sit here. Deploy something! - [Signup](https://dash.fortrabbit.com/signup) - start your first free trial - [Explore the documentation](https://docs.fortrabbit.com/platform/new) Found a bug? Have a feature request? Love something? Hate something? We want to hear about all of it. Start a chat using the chat bubble or email us at [support@fortrabbit.com](mailto:support@fortrabbit.com). ## Thanks Thank you to everyone who made this possible - our incredible team, our patient alpha testers, and our loyal existing customers. It's a big drop for us. It's so many things. When it works out well, magic happens and the service becomes more than just the sum of its parts. Here's to the next chapter of fortrabbit. 🚀 --- - [New platform BETA details](/platform/new/beta) # New Relic BYOL Source: https://blog.fortrabbit.com/new-relic-byol Created: 2014-05-20 Author: Oliver Stark Tags: chronicles, changelog > New Relic support lands on fortrabbit under a bring-your-own-license model, with the daemon running on the platform side. New Relic support is one of the [most requested](http://fortrabbit.com/feature/new-relic-support) features here on fortrabbit. Two months ago we [silently](http://fortrabbit.com/changelog) launched a beta version . Now we are finally releasing our first version of New Relic support. ### How New Relic BYOL works For now you have to Bring Your Own License (BYOL) to use New Relic on fortrabbit. To do so, you [create a new account over at New Relic](https://newrelic.com) and add a new application to reveal your license key. Next, you enter this key in the fortrabbit dashboard under **Your App > Settings > PHP > Debugging**. Behind the scenes we install the PHP extension, start the background daemon and after a few minutes you App will send data to New Relic. ![PHP_Settings](/images/new-relic.png) Enable the New Relic at fortrabbit: Your App > Settings > PHP > Debugging ![NewRelicDemo](/images/new-relic2.png) New Relic Dashboard The most impressive features like Transaction Tracing and SQL Query Analysis are not present in the new Relic free plan, but it's worth to start the 14-day free PRO trial. You will become addicted! ### How it will work in the future The current solution is just an intermediate step. We will create an [Add-Ons](http://fortrabbit.com/feature/3rd-party-add-ons) market place where you will be able to easily book all kind of external services from fortrabbit directly. We are already talking to New Relic and are looking forward to bring both services together more tightly, including a pricing similar to other integration partners. # The new stack chooser Source: https://blog.fortrabbit.com/new-stack-chooser Created: 2016-08-04 Author: Frank Lämmer Tags: changelog > Pick a framework or CMS when creating an app and fortrabbit sets the matching configuration — no one-click installer, but a running start. Sorry, no one-click hosting here — Framework/CMS will not be installed automagically. It's rather a cool helper tool and it is available for every New App you create. Besides the easier setup, new deep-links from your App in the Dashboard directly to the new [dynamic help](https://help.fortrabbit.com/access-methods#toc-the-code-example-helper) are provided. This gives you copy&pastable code examples matching your needs right away. In short: Everything is easier. You are welcome. ## Why we are doing this We dug deeper into what our users were doing after sign up. We found out that far more people than anticipated seem to be stuck right after their first code deploy. To give you an example: Laravel needs to have the root path set to `public`. A lot of new users missed that part in our [install guide](https://help.fortrabbit.com/#install-laravel) and thus ended up seeing a 403 instead of their just deployed Laravel. 95% of our users are using one of the stacks in our helper anyways (guess which is used the most!). We think it helps everybody to have the App up and running more quickly. ## Some more details **The setup is opinionated.** The configs are aligned with our [install guides](https://help.fortrabbit.com/#install-guides). It is assumed that you are using [App secrets](https://help.fortrabbit.com/app-secrets) and [Object Storage](https://help.fortrabbit.com/object-storage). For [WordPress](https://help.fortrabbit.com/install-wordpress) we promote to use Bedrock. **The setup is non-destructive.** You can delete, change and overwrite all the automatic generated setting. It's just a helper tool to get your started. The initial configuration is not hard coded into your App: You can choose to run an entirely different stack than you have selected when creating the App at any point — if you want to. Here are the configurations we set up for you, depending on the stack you choose: #### Craft CMS - root path: public - ENV vars: CRAFT_DEBUG, CRAFT_CACHE, CRAFT_UPDATES - App secrets: CRAFT_KEY #### Drupal 8 - root path: web #### Laravel - root path: public - ENV vars: APP_ENV - App secrets: APP_KEY #### Phalcon - root path: public - PHP extension: Phalcon - PHP version: 5.6 #### Symfony - root path: web - ENV vars: SYMFONY_ENV #### WordPress - root path: web - ENV vars: WP_ENV, WP_HOME, WP_SITEURL - App secrets: AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY … ## Other updates ![Contributions on GitHub](/images/help-work-graph.png) We are currently updating our [help pages](https://help.fortrabbit.com). All articles are getting re-edited, checked and extended. Framework/CMS install guides are getting updated to the latest versions (Phalcon 3 will take a little longer, we will introduce it with the next minor PHP update). We are also introducing some smaller styling updates to Dashboard and other properties. Cheers! # New Worker Component released Source: https://blog.fortrabbit.com/new-worker-released Created: 2016-01-20 Author: Oliver Stark Tags: changelog > The Worker component moves long-running background tasks out of the web request, so customer-facing responses stay fast. ![Screenshot of the New Worker](/images/worker-screenshot.png) The idea is to separate your App into front-end tasks from back-end tasks: Your front-end tasks are customer facing so they need to be executed quickly. Hence move everything which can take long to the back-end. There, tasks can take much longer without being annoying. The most common approaches are utilizing queues and scheduling execution times. The Worker is an optional Component for your Apps to achieve exactly that. Read all about how to leverage the Worker Component in our [help](http://help.fortrabbit.com/worker). ## Differences to Old Workers We have first introduced Workers in [August 2013](/worker-addon-released). Now — with all the learnings — we are releasing a redesigned solution. Most notable is that there is a new, smaller and much more affordable entry level plan — which was a hugely requested. This opens the range of use cases for smaller applications. Apart from that, there is a **price drop of 15% - 30% across all plans**. And last not least: the New Workers are easier to understand and work with. The New Worker is now available for all New Apps, the Old Worker stays available for Old Apps. If you are already familiar with the Old Workers, here is what you should know: ### Old Workers - runs on a dedicated SSH Node (full Linux instance) - managed via `scheduler.yml` file & remote SSH - plans vary in different RAM sizes and CPU power - log access via SSH file + tail (10 seconds delay) ### New Worker - runs in a container (different visualization layer) - managed via Dashboard & SSH CLI - plans vary in dedicated RAM sizes and number of active Jobs - live log access via SSH CLI command ### Pricing changes in detail | Old plan | Old specs | Old price | New plan | New specs | New price | | ---------- | --------------------- | --------: | --------- | -------------- | --------: | | — | — | — | Worker s | 128 MB, 1 job | **5 €** | | Workers xs | 400 MB, micro CPU | 17 € | Worker m | 512 MB, 4 jobs | **15 €** | | Workers s | 1.5 GB, small CPU | 35 € | Worker l | 1 GB, 8 jobs | **30 €** | | Workers m | 3.5 GB, medium CPU | 80 € | Worker xl | 2 GB, 16 jobs | **60 €** | | Workers l | 3.5 GB, high freq CPU | 140 € | — | — | — | Now, these pricing specs might look mostly same at first glance. But please be assured that the New Workers are much faster. They run on the CPUs which are two generations ahead and are backed with SSDs. Also note that the RAM for the New Workers is fully available reserved for the tasks to run, while the Old Workers shared the memory with the Linux system. The old "Worker xs" was considered for development only. The new "Worker s" advertised to use in production (and we tested that). We do not offer high availability options for Workers at this time. Apps should be resilient and not rely on the availability of a Worker anyways. ## Old > New migration time-line When is best time to move from Old App to New App? Well, now is good — but you still don't have to. It depends on your needs: should your App rely on Workers it just got way more attractive. We are currently working on the last mile stone to make the New Apps feature complete: The "asset storage", a way to work with files generated by your App. As soon as this feature is released, we will actively push the move towards New Apps. The plan is still to migrate all Apps by mid 2016, but it will take as long as it will take. We will listen to your feedback and will help you as much as we can. ## Up next We are finally getting ready to come to the US. [Sign up](http://eepurl.com/bNbHmr) for a one time mailing to be notified about the launch, or just [follow us on Twitter](https://twitter.com/fortrabbit). Thanks so much for your interest and your trust in is so far. What do you think of this release? Do you have any other ideas? Your feedback helps us heading in the right direction. The worker photo above makes use of this [image](https://www.flickr.com/photos/kheelcenter/5279252789/) by Kheel Center. # New year cleanup Source: https://blog.fortrabbit.com/new-year-cleanup-maintenance Created: 2014-01-30 Author: Ulrich Kautz Tags: changelog > Announcing scheduled maintenance work for the new year, what will be touched and which downtime to expect on hosted apps. Same procedure as every year: the new year cleaning is about. For a hosting provider that might be a bit different than for oneself at home, but in a sense the same. We're hereby announcing upcoming maintenance work in two weeks on Thursday 13th February **Monday 17th February 2014**. ## The stick Let's start with the bad news: Of course we try to make this as painless as possible for anybody, but out of necessity, it will not be completely downtime less. Here is what you should expect: * Short downtime (1-3 minutes) for all Apps due to replacement of our load balancers * Additional short downtime (2-4 minutes) for all non HA Apps, due to restart of PHP application servers * Short downtime (~5 minutes) of all deployments (SSH/SFTP and Git) and Workers We will provide more detailed information closer to the event on twitter. The load balancer restart passed all tests with flying colors and shall complete without problems. However, one of the reasons why we are **not** recommending to use IPs (A-records) is that it is not completely impossible that we "lose" an IP (although it's a very, very tiny risk). If you want to be on the safe side (and use A-records) we recommend to set the TTL your A-records to the shortest possible interval (60 seconds would be perfect) two days before the maintenance - so you could switch over to a new IP immediately. ## The candy Now you had the stick, here is the candy: **Faster startup**: App creation and unfreezing will be generally faster, up to three times. **Faster PHP updates**: We will be able to update PHP minor versions much faster. So 5.4.x to 5.4.y will be there within days after release. Same goes for extensions. **General internal upgrades**: Thew new year cleaning will bring a variety of small upgrades of _background_ tools, eg: Image Magick: 6.6 -> 6.7, Git: 1.7 -> 1.8, ... **More PHP extensions**: Then there will be some new PHP extensions: gnupg, ldap, solr, riak, ev and libevent for the Worker, Preparing for (Zend)Opcache and APCu. **Back to the future**: And the major reason we're doing this now is to prepare for upcoming releases: * PHP 5.5 goes in final internal testing and will be available shortly * [New Relic](http://fortrabbit.com/feature/new-relic-support) support goes in internal beta * [HHVM](http://www.fortrabbit.com/feature/hhvm-support) goes in internal alpha and we start pounding it **Update**: The upgrade is done by now. All machines have been replaced. In the process, we also switched to the latest generation of AWS instances. The large majority of the Apps should have experienced the small downtimes as announced. A few Apps had troubles and it took us longer to get them up again. Sorry for that! For all worker users: the workers needed an emergency restart and lost their SSH host key: you'll be warned about a new key by your SSH client on the next login (don't panic). Everybody experiencing something that should not be happening: give us a holler! # Object Storage launched Source: https://blog.fortrabbit.com/object-storage-launched Created: 2016-04-21 Author: Frank Lämmer Tags: changelog > An integrated S3-compatible object storage for uploads, runtime data and static assets, easier to set up than S3 itself. ## Why you'll want to use it * It's a best practice for modern web applications. * Decouple code from the contents. * Keep your Git repo clean, lean and thus the deployment fast. * It's far easier to setup and use than S3. * It's cool. * It's fun. * It's fast. * It's highly available. ## How much it costs You can choose from one of our reasonable plans. Please see our [pricing specs page](https://www.fortrabbit.com/old-platform/specs-uni) for all details. In most cases it's a little more expensive than using AWS S3 directly, but it's far easier to use and without a complex pricing model attached as well. ## How it is integrated You probably already know how to use it: it pretty much works like AWS S3, because it implements the S3 REST API. It is closely integrated with your fortrabbit App, so you don't need an extra service nor fight with complicated IAM rules. ## How to use it There is a multitude of options. Most common: your App will access the Object Storage on a programmatic level — file system abstraction is the key here. There are two popular Composer packages which are bundled with most modern frameworks / CMS. See our comprehensive [help article](https://help.fortrabbit.com/object-storage) to get you started quickly. ## What else is in it You get an individual URL per App: `https://your-app.objects.frb.io`. All HTTPS requests are served via **HTTP/2**. Due to our caching strategy the vast majority of requests will be delivered straight from memory, which is the fasted I/O possible. We do not differentiate between Production and Tinkering because all plans run on high available clusters. ## What's next For existing clients we advise to migrate Old App to New Apps now. There is - however - still time and we don't rush you. We also will put some efforts to help clients with the transition from Old Apps to [New Apps](https://help.fortrabbit.com/new-apps). Please ask us when you need help. ## How we got here It took some effort to get here, but now we are proud of this release. We started this journey towards a new platform over [a year ago](/roadmap-to-hack-app). Now the New Apps are finally feature complete in the sense that all components are available for the New App which were available for the Old App. Also we achieved our goals: The New Apps are more advanced, much faster and more affordable. ## What really matters Your feedback. Please tell us what you think by answering two questions below: # Old App migration program Source: https://blog.fortrabbit.com/old-app-migration-program Created: 2017-03-20 Author: Frank Lämmer Tags: changelog > We are manually moving many Old Apps to Universal Apps to avoid downtime and data loss for stragglers. **We will manually migrate most Old Apps to the Universal Stack.** Old App applicable for the migration program (see below) will be moved to the new Universal App infrastructure, this includes all files and the MySQL database contents. ## Which Apps are going to be migrated **We can migrate most, but not all of the remaining Old Apps:** Some of the [Old App](https://help.fortrabbit.com/app-old) are making use of features currently only available with the [Professional Stack](https://help.fortrabbit.com/app-pro). As the Professional stack and the Old App stack are [different by design](https://help.fortrabbit.com/stacks) an automated migration by us is not possible. So only Old Apps that fit within the technical range of the current Universal Stack will be migrated. ### Old Apps not applicable for migration * Apps using the Memcache Component * Apps using the Worker Component * Apps that need high availability options * Apps with very high traffic **We will shortly contact all affected clients with personalized e-mails including detailed informations which Apps will be moved by us and which won't be.** ## What it will cost The Old App migration service itself is provided free of charge - of course. Universal Apps are more affordable than the Old Apps. The Old Apps will be mapped to the new pricing plans. For some bigger sized Apps, for which we don't have a fitting Universal plan, we have prepared custom larger plans not available on our website. Bottom line is that the Apps will cost either the same or less after migration. As usual, you can cancel the whole service or certain Apps at any time with immediate effect. Before or after migration. ## When it will happen The migration is planned to happen between Saturday, **April the 1st 2017** and Sunday April 2nd 2017. Please note that this is NOT an April fools, it's the closest weekend day to the official sunset date and we hope that less visitors will be affected by choosing that date. We expect a **downtime for about 8 hours** from start to the last App - individual Apps will become available sooner. ## Why we can not promise that it will work for you This migration program is our last resort to help. **We can not guarantee a successful migration** since the Universal infrastructure is more modern and comes with newer software versions. Possible issues: ### PHP upgrade from 5.5 to 5.6 The newer PHP version brings some changes which might cause problems in certain scenarios — overall rather unlikely. ### MySQL upgrade from 5.5 to 5.7 The newer MySQL version might cause problems with old applications. It should not cause problems for recent CMS and framework versions. ### Hard coded absolute paths Any hard coded absolute paths in the form `/var/www//htdocs/some/path` will become invalid. The location has changed to `/srv/app//htdocs/some/path` for Universal Apps. ## What you can do to help Are you one of those "lazy" clients? We are in this together. Please help to make this one successful and as smooth as possible. ### Before migration #### Find out if this affects you * Is your fortrabbit App three years or older? * Check the mails we have sent you! * Login to the [fortrabbit dashboard](https://dashboard.fortrabbit.com). Old Apps are marked yellow. With the App itself you will see informations if your App is legit for the migration program. **When your Old App is NOT part of the migration program:** Please mind that all Old Apps will be destroyed at the end of March. We won't keep backups longer then a few days after the removals. Backup all the data before switch off yourself. We are happy when you continue to use our service by migrating to a new stack (see links to guides below). #### Review if you still need your Apps We have found many neglected projects among those Old Apps — think Zombies. Take this as a chance for some spring cleaning! Check all your running Apps, if you still need them, if not delete them in the Dashboard. This saves costs on your and efforts on our side. Also, if you just don't want to be migrated for any reason, just let us know so we'll move you of the list and your Apps will expire. #### Consider to do the migration yourself If you are affected, maybe reconsider migrating on your own. You know your App much better then we do and it's far more likely that the App migration done by yourself leads to far less downtime then our "big batch". Here are extensive migration guides: * [Migrate Old App to Universal guide](https://help.fortrabbit.com/migrate-old-to-uni) * [Migrate Old App to Professional guide](https://help.fortrabbit.com/migrate-old-to-pro) And, of course: We are here to help you with hands on support. #### Review and update DNS settings Make sure that you use CNAME routing for all your domains. We will keep the old App hostnames (`app-name.eu1.frbit.net`) and route them on our end to the new App hostname (`app-name.frb.io`). All domains routed via A record (=IP) will still point to the old IP which will become not responsive with the shutdown of the old infrastructure. ### After migration #### Check your App Test if it's still working. **Get in touch if something doesn't work** - we are here. #### Regain data access During migration your App(s) will get new access details for SSH, SFTP and Git. Your pre-installed public SSH keys will be ported. Please revisit your App in the fortrabbit Dashboard to grab the new access credentials. Here the general idea: * **SSH/SFTP hostname** * Old: `ssh123.eu1.frbit.com` * New: `deploy.eu2.frbit.com` * **SSH/SFTP user** * Old: `u-` * New: `` with SSH public key or `.` for password authentication * **Git URL** * Old: `git@git.eu1.frbit.com:.git` * New: `@deploy.eu2.frbit.com:.git` In addition, the App URL and the MySQL hostname will change as well (MySQL user and password will stay the same). However, we will re-route the old hostnames to the new ones, so you won't need to change them - although we recommend it: * **MySQL hostname** * Old: `.mysql.eu1.frbit.com` * New: `.mysql.eu2.frbit.com` * **App URL** * Old: `http://.eu1.frbit.net` * New: `http://.frb.io` ## Final words "Keeping your business online is our business" is not only a marketing slogan of ours, it's part of our company philosophy. We understand that our client's time is precious and it was maybe too easy to mark our our efforts to reach out as read. Thanks for being with us for such a long time. We are very proud to have you on board. We are sorry to bother you with this, but, you know, time doesn't stand still. Thanks for reading and take care! # On horizontal scaling Source: https://blog.fortrabbit.com/on-horizontal-scaling Created: 2024-07-05 Author: Frank Lämmer Tags: opinion > Why the new fortrabbit platform drops horizontal scaling, a signature feature of the Pro Stack, and what replaces it. ## The two stacks with the current platform For the current platform we have the Uni Stack and the Pro Stack. That is not a marketing trick to lure more money out of wealthier customers, but part of our legacy. The two stacks are different technical implementation. Our historical approach was to 'build the hosting platform we wanted to use ourselves'. The result was the Pro Stack. It was build on top of modern paradigms to serve high performance PHP web applications. But it turned out that some aspects of it were too advanced - think unnecessarily complicated - for many use cases. To use the Pro Stack one need to: - Deploy by Git, no direct file access - Deal with ephemeral storage, Object Storage for assets, Memcache for sessions Apart from that, the Pro Stack has individually scalable components and of course offers horizontal scaling for PHP in different groups (development, production, dedicated). ## How does horizontal scaling work anyhow? With our horizontal scaling an app is distributed over multiple PHP/Apache servers (we call em Nodes). A load balancer (pair) in front will distribute all the requests coming in to the available PHP Nodes, 2, 4 or even 8. Horizontal scaling can be used as a failover solution to improve uptime. When one Node fails, it will be cancelled out and the other Node will take over. Horizontal scaling can also carry higher traffic loads. ## Reality check Our Pro Stack is great. But it is not for every one and all use cases. So we also created the Universal Stack to better support small websites build in PHP - promoting but not enforcing best practices. Choosing the right Pro App scaling isn't straight forward. There are multiple options for the same price. Clients need to know their requirements to distribute available RAM over Nodes. It's not easy and many clients end up with sub-optimal settings. I sometimes advice customers about this when inspecting performance issues with clients. Apart from choosing the right scaling, some implications of horizontal scaling are tricky too. We try to counter this with good documentation and helpful support. Our current Pro Stack also has some shortcomings that we are not a 100% happy about: The missing ability of historic logs (only log streaming) for example. There are also known edge cases, in which the failover mechanism (one Node is down) is not working as intended. We invested a lot over the years to mitigate and prevent such issues, but it's still not perfect and might never be, since what is happening also relies on the code of the clients. Overall, although designed for resiliency, the real world uptime by the Pro Stack was not much better than from the Uni Stack. That's partly because there are more moving parts with the Pro Stack, partly because of misconfiguration by clients (, partly also because we over-delivered with Uni Stack uptime). Having two stacks introduces a lot of complexity. We need to communicate two different pricing pages and for the docs we need to sections for Pro and Uni as well. For each support request, we need to check whether this is about a Pro or Uni App. This overview barely scratches the surface. There is a lot to it. We didn't took that lightly. It's not only a technical question, but also about our business. ## Unified platform vision Of course we want to have one stack going forward with the [new platform](https://new.forttrabbit.com) (in the making). Optimally - of course - there would be a smooth transition between vertical and horizontal scaling. But given the above mentioned design differences between the stacks, I am not sure if blurring those borders would be a win. We analyzed our Apps and found that only a small percentage truly needs horizontal scaling. Additionally, many workloads can be effectively handled with increased vertical scaling options on the new platform. This allows us to support 98% of our current applications with no or just minimal code changes. ## Project Cephalopod The need for ephemeral storage (12 factor architecture) with a horizontally scaled system is what makes the architecture so different. Ephemeral storage is required, since each Node (server) has it's own local file system attached. We have experimented with network attached file systems in our early days. Think each Node has access on the exact same files. Unfortunately the performance, due to latency, was not good enough. We have a new project going to test that something similar with todays software and hardware. If successful, it would, beside other benefits, enable horizontal scaling without design changes nor other compromises. But the project is in an early stage and considered an experiment for now. ## There is still a lot of time Our aim is to launch the [new platform](https://new.fortrabbit.com) later this year, 2024. We plan to start with a BETA period. During that time the two platforms will run side by side. Once the new platform will reach production grade, we will start the migration period. We plan to actively support clients to move their apps over. Where possible, we will do the migration. We plan to contact clients individually with enough time upfront and actionable details. ## Conclusion Although this may sound odd for a modern php cloud hosting provider: We plan to offer only vertical scaling for the new platform to get started. But it will come with more powerful dedicated resources to cover most of todays workloads. If project Cephalopod turns out to be successful, we will be able to offer horizontal scaling again without todays technical limitations. # On password security Source: https://blog.fortrabbit.com/on-password-security Created: 2015-03-10 Author: Frank Lämmer Tags: changelog > Password rules sit between usability, culture and security. What a security researcher's review changed in the fortrabbit dashboard. ## Prelude Some time ago security expert Mayank Bhatodra approached us with various topics on how to make our service even more secure. Thanks to his feedback we could implement various security enhancements in our old Dashboard. I asked him recently to check out our new Dashboard for security vulnerabilities. Beside other topics we discussed minimum requirements for our users to enter their Account password: ## Q: Force secure passwords **Mayank**: When signing up to fortrabbit your password entry field is a bit lame. I can enter the same email address I have used above as a password, or I can enter stuff like xxxxxxx as a password. Protect your users from making such stupid mistakes. Avoid the risk of stealing/bruteforcing passwords. Check out yahoo here: suppose your email is "frank@email.com" and you want to set your password like "frank12345" — yahoo would reject this password. You also allow simple passwords. Your only rule is a minimum of eight characters. I was able to set my password "12345678". Anyone can crack a password like that. My advice: create a robust rule set for password quality, include upper lower letters, special characters. ## A: Let's raise awareness **Frank**: We have discussed that internally during development and settled with the current solution. Our company philosophy is to "encourage not enforce best practices". Our audience are sophisticated developers. I know that they are smart and very aware of such issues. I also know that a lot of clients are already using password managers. > Let's not baby-sit anyone while entering passwords. I don't appreciate told what to do by any service. As you know: I am usability nerd and I know that ease-of-use often comes at the expense of security. We even have this unmask password thing. There are [strong advocates](http://www.nngroup.com/articles/stop-password-masking/) for actually never masking passwords in the first place. I believe that giving users the possibility to enter something they can see allows more complex passwords right there in place without switching to the text-editor, typing it there and pasting it back. Pass-phrases instead of passwords are generally better — though [within limits](https://www.cl.cam.ac.uk/~jcb82/doc/BS12-USEC-passphrase_linguistics.pdf)). But that again is something you can suggest not expect. We have looked at several password strength checkers/meters, but at the end didn't use any of them. Yep — they can help, but some are not realistic. Also, what if that fancy thing breaks with a newer jQuery version? Without wanting to sound defensive: We have checked some other developer services: Heroku lets you in with "asdasdasd", Atlassian lets you in with "asdasd", GitHub is a bit more strict. So at least we are not alone here. I also see two signup use cases for our service: 1. **for real scenario** — sign up and use it in production immediately 2. **let's try this out** — check out if it works as advertised The majority of users is there for the second option — try before buy. So why the hassle when you only want to spin up a testing App now? We already have plans to make a test drive possible, even when you are not logged in. At which point we might reconsider our stance on the required password security. Internally, we have also discussed social logins — allowing users to identify with GitHub, Google, Twitter or alike via OAuth — but ended up not doing it, for now. But we are looking forward to bring multi-factor-authentication as an additional — optional — security level. ## Additional resources * [Our security guidelines](http://help.fortrabbit.com/security) * [DropBox Blog: zxcvbn: realistic password strength estimation](https://blogs.dropbox.com/tech/2012/04/zxcvbn-realistic-password-strength-estimation/) * [Coding Horror: Passwords vs. Pass Phrases](http://blog.codinghorror.com/passwords-vs-pass-phrases/) * [Comptechdoc: Password Policy](http://www.comptechdoc.org/independent/security/policies/password-policy.html) * [Luke Wroblewski: Showing Passwords on Log-In Screens](http://www.lukew.com/ff/entry.asp?1941) # On upcoming PHP deadlines Source: https://blog.fortrabbit.com/on-php-deadlines Created: 2018-09-06 Author: Frank Lämmer Tags: opinion > PHP 5.6 and PHP 7.0 deadlines: Why is so much old PHP around? What we will do!

Only days until the end of live for PHP 5.6 and PHP 7.0. Why update? Why is there so much old PHP out there? How to establish an up-to-date mindset.

This is part one of a series on the approaching end of life of PHP 5.6 and PHP 7.0. This is the long read, the general theoretical part including details and philosophical questions. In the next parts more actionable instructions on how to actually migrate, especially for fortrabbit clients will be included. As time flies by. Only three years ago, we announced that [PHP 5.6 is becoming the new default](/php-upgrade-path-5-4-5-6-7-0). Now, we are already facing the end of that and even the ascendant version 7.0 . ## Why upgrade to PHP 7.2 anyway? **It's about time.** "PHP 5.6" is the last 5 version around and there will be no security patches from December 2018 on. Any new vulnerabilities will not get fixed any more. The same applies to the initial PHP 7 release, version 7.0. It was released in December 2015. The current version is PHP 7.2 and PHP 7.3 is approaching next. ![php deadlines approaching](/images/php-version-deadline-on-php-net.png) See the [officially supported PHP versions and there lifespans here](http://php.net/supported-versions.php). ### How much old PHP is still around? ![php usage according to w3techs](/images/php-usage-according-to-w3techs.png) As of August 2018: PHP 5 is still the most used version of PHP. According on who you are asking, you will get different answers: - **~80% old PHP** according to [W3Techs](https://w3techs.com/technologies/details/pl-php/all/all) (PHP 7 also includes the deprecated PHP 7.0) - **~66% old PHP** according to [WordPress](https://wordpress.org/about/stats/) - **~21% old PHP** according to [Composer](https://seld.be/notes/php-versions-stats-2018-1-edition) Why the differences? Well, I believe **W3Tech** is just crawling the web sniffing the `X-Powered-By` header to get the version in use today. That includes all the public IPs with all the neglected websites out there. As this gives potential hackers information about the PHP version, it's common practice to suppress or fake this header, so maybe take this number with an extra grain of salt. **WordPress** is luckily a little ahead, as it is an active community of "web designers", with a big stake in the United States. And of course, Jordi with **Composer** is ahead, as those PHPeople are mostly "web developers" who care more about such things. ### Who is to blame for all the old PHP? We started fortrabbit, around 5 years ago, because we were thrilled by the new PHProfessionality. Composer, Laravel — for us PHP really made the switch to a modern programming language. Still PHP has a bad rep for being the Pretty Home Pages language — and that is also still true. PHP was and still is (beside JavaScript) the first web native language to pick to create home pages. And many of those websites are still around. It's all those tiny businesses and their **semi professional web designers**. When you receive $200 to build a website for a restaurant, you are not likely to maintain it for the next 10 years. And it's the **mass of shady shared hosting providers** who are keeping the clients locked-in in long term contracts and outdated versions. I can imagine that half of those PHP 5.6 websites could actually be switched off by now. But that's not the interest of the hosting providers, they are more interested in keeping them around. ### Our conflict of interests It's tricky. Even here — with PHP cloud hosting fortrabbit — around a quarter of Apps are still running on PHP 7.0 and PHP 5.6. Luckily it's more PHP 7.0 and less PHP 5.6 which will make the transition less painful. Still it's a few hundred Apps and that's some good revenue for us. Most of those Apps are old of course, they have a life time of at least 14 months and sometimes even much or more. So those Apps are already older than the average App here — more likely to churn soon. We expect to find lot's of neglected projects their owners forgot about in there. Now, when we will start to inform the owners about upcoming changes, chances are that many of those projects will just be killed. Either the projects are not needed, or there will be no budget for migration efforts. PHPeople will be like: > "Oh, that shit is still around? I need to take care of this now? Oh, and I haven't integrated those GDPR changes. I can cancel this right away. Cool! Let's do this instead." We will loose a good number of Apps. As a business that's of course not in our interest. ### Or shall we keep all the old PHP? We have discussed ways to deal with the situation. One idea was to keep those Apps still around, on unsecured PHP versions. Our fellow colleagues over at Platform.sh are following such an approach: Asking to upgrade but still keeping Apps on old PHP versions around - see [their blog post](https://platform.sh/blog/its-july-2018-do-you-know-what-your-php-is). The argument here is, that we should support the clients preferences as much as we can. This is technically possible here as well. We could accept the risk of someone leveraging not fixed vulnerabilities to break in, only causing some local damage. **But NO, we won't do that!** Still this could cause our IP ranges or App URLs to be down-ranked or included into SPAM blacklists. We also want our client base to be fresh, agile and alive. ### What to do about all the old PHP? What ever the real number of old PHP installations in the whole internet will be, there soon will be tens of thousands of outdated and unprotected PHP servers out there waiting for hackers to take them over. Maybe we should all gather together and raise awareness for the situation so that more PHPeople wake up and update? What about a hashtag like **`#uPHPgraded`**? Or maybe, even better, that's a call to establish new business models? Imagine, what would you do with that army of zombie servers? Bitcoin mining or even making Obama president again?

Establish an up-to-date mindset!

Keeping your own code and the underlying software dependencies up-to-date is more than just a good practice, it's a requirement. On fortrabbit, we are in this together. We are responsible keeping the infra up-to-date; your are responsible for the code you write and use. Updating keeps your code secure, fast and agile. Our clients are obligated to use up-to-date software by [our terms under 4.13](https://github.com/fortrabbit/legal/blob/master/terms.md#-4-obligations-of-the-customer). The **up-to-date mindset** requires some thinking ahead and discipline. [Technical debt](https://en.wikipedia.org/wiki/Technical_debt) is the keyword here. Consider upfront that all the code your are having out there, will constantly need some attention and time. It's easier when you are code maintainer and business owner, like with a start-up or as a freelancer on your own projects. It's more complicated in bigger structures and in client-agency relationships. Make maintenance an topic early on, include it in your estimates. **Raise awareness on the importance to keep your software up-to-date.** Reserve a time budget for that upfront. ## Our next steps We will provide further information — in much more detail and hands-on — on how migration to PHP 7.2. And we will also inform clients individually on affected Apps soon. There will be multiple mailings. We currently plan to update all remaining Apps to **PHP 7.1** in February 2019, an exact date will be announced. Feedback and questions are — as usual of course — highly welcome. ## Wrapping up We are very happy to see the PHP language under heavy development coming closer to shorter release cycles and even breaking some old habits. It's alive. Let's embrace change and move forward. # On technical limits Source: https://blog.fortrabbit.com/on-technical-limits Created: 2024-04-29 Author: Frank Lämmer Tags: webdev > Fail early they say. Don't throw hardware on performance problems we say.contributions. Our long time client Josh recently opened a [feature request GitHub issue](https://github.com/nystudio107/craft-imageoptimize/issues/402) with the Craft ImageOptimize plugin by nystudio107 (Andrew). The job to process images was prematurely ended by our system. Deployment and SSH tasks are capped at 20 minutes. Along the conversation Andrew commented on our limits: > _I'm not sure how I feel about this; it's an externally imposed limitation that normally is configurable. […] It makes sense as a default, but a way to override or change it when the client has extraordinary needs might be helpful._ I totally see where he is coming from. Yet, I have to admit that this triggered me a bit. My colleagues, Josh and I guess Andrew where all a bit surprised by my emotional reaction. Our technical server limits are quit fundamental to our approach of web hosting. Let me explain in even more words. ## Making a virtue out of necessity The fortrabbit platform (currently) runs on Amazon Web Services infrastructure. I consider AWS a premium service: good, stable, professional, worldwide scalable and a bit more expensive. As a commercial service we need to add markup on top of our infra costs to cover our operations. Many web hosting clients on the other side, are looking for the most computing power for the least money. Given our structure, we can not compete on that. Our platform architecture is different. We don’t provide VPS boxes. Apps run in containers of EC2s with other services attached, those are isolated, yet shared. In my experience hosting PHP websites and web applications usually does not require vast resources. Of course, it’s tempting to think that it is still better to have them at your disposal if you need them, but I would argue that in almost all cases a different solution than throwing hardware at a problem can be found. We picked up the saying ‘**Do more with less**’ by Buckminster Fuller a while ago and it still resonates with me. Resourcefulness should be important in todays world. A website or web application that needs a lot of computing power, bandwidth or time to serve just a few requests will not scale when demand grows. Fail early. See configuration problems early on. ## Common limits Let’s have a look at the most common performance limitations people run into: ### PHP response time Our philosophy is that frontend PHP processes should run fast. A PHP request should not take longer than 250 ms. We don’t provide a lot of parallel PHP requests. In accordance the PHP `max_execution_time` is low: 60 seconds by default, with a setting allowing only 120 seconds. On a regular basis, developers asking us to increase that value in support. But that would increase the possibility to lock up the App in 503 or 504 errors. The correct is usually to look what is taking so long and how can that be fixed. It’s often a matter of configuration. ### Database size We offer small database sizes. Yet I argue that you can store a lot of data in a 256 MB of MySQL. Exceeded database sizes are common in our support. In almost all cases misconfiguration not real requirements are the source. There are a few Craft CMS plugins, if not configured with care, that fill the database with useless rows of cache. A larger database will only make the issue appear at a later point in time. Again, we want this to become visible early. ### Traffic When looking up why traffic is exceeded I usually find un-optimised websites. Most egress traffic is caused by images and videos. [Website obesity](https://idlewords.com/talks/website_obesity.htm) is a thing. ## Communication Back in the early days of PaaS, it was a common pricing strategy to blur provided resources by inventing fantasy metrics. We aim to be clear about the actual implementation and it’s limits. We maintain a [limits](https://help.fortrabbit.com/limits) and [specs](https://www.fortrabbit.com/old-platform/specs-uni) page. To help clients, we have the [general application design article](https://help.fortrabbit.com/app-design), as well as the [Craft CMS specific performance article](https://help.fortrabbit.com/craft-performance). Last not least limits and performance related issues are hot topic with our customer support. We invest in that a lot. The best case scenario is something like this: > _I just want to say that you all make us better for our clients. The limits you set on the servers are reasonable and prevent us from coming up with lazy or hacked solutions. We are definitely better because of you all._ —Stephen Callender from Shoe Shine Design Yet, after so many years in business I have to admit that it is hard for us to land our pitch. It requires time from potential customers to read and reason about our approach. And being a customer myself with other services I can assist that is hard to give up mental models and adapt to new ideas. This could be me on any other service: ![Strong limitations](/images/strong-limitations.png) ## Outlook We do have a tough sell. But I am not tired of it. I continue to believe that the necessarily limited resources are sufficient for common usage. Most limits are even helpful to avoid bad practices. There are a few edge cases and where possible we plan to add configuration options with the [**new platform**](https://new.fortrabbit.com) (in the making). I see a lot of small projects hosted here and beside providing the required resources, my aim is to make the price match as well. This is quit an ambitious task running on AWS infrastructure and providing while providing a standardized solution. We are also elaborating a different infrastructure provider for the new platform. # Yes, we love open source Source: https://blog.fortrabbit.com/open-source-at-fortrabbit Created: 2018-07-30 Author: Frank Lämmer Tags: opinion > Props to the OSS communities and highlighting some of our open source contributions. ## Open source everywhere The fortrabbit hosting platform itself is a combination of several open source software systems to make your life as a developer a little more convenient. The operating system is Linux, Ubuntu + Debian. We are making use of LXC and Docker for virtualization. The web-servers Apache, NGINX and HAProxy are running here side by side. There is Golang and PHP itself. Not to forget about Git and Composer. And these are just the most obvious ones. The list goes on. You as a developer will most likely again use more open source here. WordPress, Laravel, Symfony or all the great Composer packages. It's obvious that there would be no fortrabbit without open source. ## How to give back **So why is fortrabbit not open source?** That's a good question. Maybe we have missed something in the initial design. Wouldn't it be great to have a community edition and a hosted edition of fortrabbit? Maybe. But so far our approach is a bit different. The platform is an abstraction layer on top of Amazon Web Services. It combines different AWS services to a single experience. In order to do so, we need to setup and actually run a base infra. It takes quite some Apps running on the infra to level out the costs, so there would not be many use cases and benefits of running such a self-hosted community edition. And there are other considerations as well. **Contributing.** Our best approach for now is by more individual open source involvement. Projects that are related to fortrabbit, more or less closely. "Follow" us on [GitHub](https://github.com/fortrabbit). # Opinionated Craft CMS 4 upgrade guide Source: https://blog.fortrabbit.com/opinionated-craft-4-upgrade-guide Created: 2022-10-11 Author: Frank Lämmer Tags: webdev > Everything you always wanted to know about updating to Craft 4 - but were afraid to ask. ## Do I need to update? This depends when you are reading the article. By the time of this writing (October 2022) Craft 2 support ended. Craft 3 will have support until 2024. Have a look at the [Craft CMS support versions page](https://craftcms.com/knowledge-base/supported-versions) to get an idea. ### Craft 2 upgrade path For people running a Craft 2 installation today, we suggest to upgrade to Craft 3 (as of this writing). Many of the following principles also apply, so keep on reading and adapt as required. ### Craft 3 to Craft 4 upgrade path The rest of the article mainly is about upgrading from Craft CMS 3 to Craft CMS 4. ## What is changing? Unlike WordPress, which seems to be feature complete, Craft CMS is under heavy development. Breaking changes are introduced with new major versions. We appreciate the improvements. * Read the [blog post advertising changes for Craft 4](https://craftcms.com/blog/craft-4) and come back here ## Should I update? It depends. If your website is actively maintained, probably yes, since new features will only come to Craft 4. If the website itself is not changing, probably not. **Mind the plugins!** Like other CMS, Craft relies on a plugin eco system, mostly written by third party authors. By the time of this writing the majority of plugins not updated to support Craft 4. However, at the official Craft conference DotAll 2022, Brandon Kelly stated 87% of most poplar plugins already available. So, it depends which plugins you rely on. ## Get ready As usual, we suggest to update your local version of Craft CMS first before deploying anything to production. 1. Upgrade to the latest 3.x version of Craft CMS first, [see our guide](https://help.fortrabbit.com/craft-update). 2. Upgrade you local development environment to the latest versions A. We suggest PHP 8.1, MySQL 8 or higher 3. Fix potential issues, [see the official guide](https://craftcms.com/knowledge-base/preparing-for-craft-4) * Fix deprecation warnings if there are any * Replace `siteName` and `siteUrl` if set * Prepare for Twig 3 * Replace GraphQL enabledForSite with status, if required ## Perform the update Read the [official guide first](https://craftcms.com/docs/4.x/upgrade.html), then come back here. In addition to that we found this useful: ### 1. Upgrade `composer.json` manually It took me (the article author) a while to research the latest plugin versions and modify the `composer.json` by hand. I looked up each composer requirement in the Craft plugin store for Craft 4 support and used the newer version. Usually there is a new major version of the plugin, accompanying the new Craft version. To get an overview of the packages you depend on directly (craft plugins and few others), composer provides a handy `composer info` command that show the current you've installed and the latest available version of the package. The command does not show if the plugin is ready for Craft 4, but if you can see a new major version the chance is very high. ``` composer info --latest --direct --no-plugins # Example output craftcms/aws-s3 1.2.11 2.0.1 Amazon S3 integration for Craft CMS craftcms/cms 3.5.14 4.2.5.2 Craft CMS craftcms/commerce 2.2.23 4.1.2 Craft Commerce craftcms/mailgun 1.4.3 3.0.0 Mailgun integration for Craft CMS fortrabbit/craft-copy 1.2.4 2.1.1 Tooling for Craft on fortrabbit mattstauffer/happybrad v1.2 v1.2 Add a Happy Brad to your Craft CMS Dashboard. ostark/craft-async-queue 2.1.1 3.1.0 A queue handler that moves queue execution to a non-blocking ... ``` #### Your plugin is not updated? You may find that a plugin you are using is not ready for your new Craft CMS version. That can become a deal breaker. Go to the GitHub repository and see if it is under development. Maybe there is already an issue to support Craft 4, maybe even a dev branch, or an ETA. Maybe there is an alternative plugin, or you may not really need the plugin at all. If not, consider writing a patch and a PR for the plugin yourself. There are [Rector rules](https://github.com/craftcms/rector) to update plugins to work with Craft 4. ### 2. Update DotEnv (opinion) We advice to update `vlucas/phpdotenv` to the latest version as well. Depending on when you initially installed Craft, you may find the version in your composer.json much older. For this to work, you best have the latest PHP version. * [vlucas/phpdotenv on GitHub](https://github.com/vlucas/phpdotenv) ### 3. Update Craft core files (opinion) When updating Craft CMS, only files in the vendor folder are going to get changed. There are some files that have changed and have been introduced outside. We advice to manually update the following local files with the linked sources: * [/craft](https://github.com/craftcms/craft/blob/main/craft) * [/web/index.php](https://github.com/craftcms/craft/blob/main/web/index.php) * [/bootstrap](https://github.com/craftcms/craft/blob/main/bootstrap.php) - new file ### 4. Composer update Still with your local development, run `composer update` then cross your fingers. Resolve dependency issues, if any. This may be hard. We can not cover this here. ### 5. Run migrations After updating via composer, run migrations by issuing `./craft migrate/all` on your local terminal. ### 5. Test your local website Now you may made through the hard parts and you already have updated your local installation of Craft CMS. Make sure to test it. This includes the frontend and the admin and of course all plugins. If you encounter 500 errors, check the PHP error logs and resolve the issues. * I found that there Craft 4 is more strict about settings in `general.php`. I had to remove `'useProjectConfigFile' => true`. * Also there seems to be a new format for log file naming, now including a date string. ### 6. Check your web hosting environment See if your local versions of PHP and MySQL are matching the ones with your web hosting provider. With fortrabbit you can easily change the PHP version. ### 7. Delete the vendor folder with your fortrabbit App This likely only applies to fortrabbit clients with Uni Apps. The template file names extension has changed (`.html` -> `.twig`). Since we have an overwrite but not delete strategy, the wrong files may still be picked up. Actually Craft CMS should prefer `.twig` now, but it doesn't. See [discussion](https://github.com/craftcms/cms/discussions/11809). So before you deploy the update to your fortrabbit App, login by SSH and delete the vendor folder, or all `.html` template files in it. This will break the site. Deploy right after. ### 8. Deploy changes Now you only need to get the updates up on your remote web server. This should be standard routine. We advice to use our Craft Copy plugin ([GitHub](https://github.com/fortrabbit/craft-copy)) for this. If not using Craft Copy, make sure that: 1. code changes are ending up on the server 2. composer install will be run 3. migrations are applied ### 9. Test it again in production Since your local environment and you production environment may differ, make sure to test everything again in production. ## Done Easy-peasy. Wasn't it? ## Extras ### Mind that the ENV var naming schema has changed `DB_PASSWORD` now is `CRAFT_DB_PASSWORD` and so on. Make sure to apply the new schema with the `CRAFT_` prefix to your `config/db.php` and other config files that make use of ENV vars. ## Related Craft CMS reading - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — tune the freshly upgraded site. - [Craft CMS CVE 2025-32432](/craft-cms-cve-2025-32432) — high-impact RCE; another reason to keep current. - [Craft CMS CVE-2023-41892](/craft-cms-cve-2023-41892) — earlier vulnerability worth checking after the upgrade. --- - [Craft CMS guides](/guides/craft-cms) # Optional PHP extensions Source: https://blog.fortrabbit.com/optional-php-extensions Created: 2013-01-31 Author: Frank Lämmer Tags: changelog > A new PHP settings page in the dashboard lets each app switch optional PHP extensions on and off without a support request. Our new PHP settings page is huge. ![php-settings-dialouge](/images/php-settings-dialouge.png) # The story of our new ENV vars edit experience Source: https://blog.fortrabbit.com/our-new-env-var-edit-experience Created: 2026-04-08 08:38:48 Author: Erin Strand Tags: chronicles > Building an environment variable editor that handles multiline values, special characters and a base64 helper without feeling clever. ## New fancy base64 helper If you prefix an environment variable value with `fr+base64:` we validate that the following string is base64 encoded, and then automatically decode the variable in the live environment for you. This is what it looks like: ![Edit ENV vars](/images/env-var-edit.gif) And here's how we got there: ## It starts with a support request A customer reported that an ENV var with a password mysteriously showed an incorrect value in PHP. Somehow, a string similar to `O3~YR$FK@8R.0X` turned into something else. The value `O3~YR$FK@8R.0X` was shortened because `$FK` was interpolated to an empty string. Similarly, if the string were `O3~YR$FORTRABBIT_DB_NAME@8R.0X`, it would replace `$FORTRABBIT_DB_NAME` with the database name. This interpolation is needed when customers set `CRAFT_DB_USER: '${FORTRABBIT_DB_USER}'`. It's also sometimes used by default in Laravel, for example: `VITE_APP_NAME: ${APP_NAME}`. So, we want interpolation sometimes, but not always. ## Old platform Dollar signs were not allowed at all. But interpolation still worked! How? When a customer entered `NAME=${VALUE}`, it was transformed internally into `NAME=%%%VALUE%%%` and then put back before being handed to the app. To handle passwords with dollar signs, we instructed customers to base64 encode them themselves. ## New platform Dollar signs, double quotes, and many other characters that were forbidden on the old platform were allowed on the new platform. However, backslashes and single quotes were still not permitted. The platform safely interpret and export all defined ENV vars to the live environment, including those that have interpolation like `CRAFT_DB_USER: '${FORTRABBIT_DB_USER}'`. But, we don't always want interpolation. ## Possible solutions We discussed next steps with the team, since it required contributions from everyone. ### 1 - Escape dollar signs In the dotenv world, the solution is to escape all dollar signs with `\$`. For example, customers would enter `123\$FK@45` to get `123$FK@45`. However, the backslash character is forbidden because it would allow customers to enter the few characters we have forbidden and possibly circumvent our safe parsing. ### 2 - Use single quotes In Bash, surrounding a value with double quotes (`"123$FK@45"`) interpolates it, resulting in `123@45`. However, single quotes (`'123$FK@45'`) prevent interpolation, resulting in `123$FK@45`. Unfortunately, this difference is not supported in `.env` files (e.g. in `vlucas/phpdotenv`), so customers copying content from them won't be aware of this Bash feature. Additionally, our backend strips all quotes from variables and values are rewrapped in quotes when used. So we cannot easily make the platform see a difference in quotes. ### 3 - Base64 encoding tool We tell customers to prefix problematic ENV var values with `base64:`, the infrastructure then automatically decodes the base64 encoded value after interpolation has happened. The dashboard can also offer a small widget to easily encode/decode values to base64. Additionally, we should disallow lone dollar signs to give customers an early error, ensuring they base64 encode passwords that include dollar signs. - Disallow single `$` - Allow `${` when properly closed with `}` for interpolation ## Gotcha Testing the base64 encoder with a wonderful customer revealed an oversight. Laravel already has a `base64:` helper for ENV vars, which interferes with our implementation. This is because our implementation cannot allow [NULL characters](https://en.wikipedia.org/wiki/Null_character), but the Laravel implementation does. Laravel's automatic `APP_KEY` generator also often generates keys with NULL characters, so they are commonly used. This meant that we could not mix our base64 decoder with laravels implementation. ## Finally solved Our helper prefix is now `fr+base64:` to differentiate it from Laravel. When used in an ENV var in our dashboard, we automatically decode the variable after the interpolation is done. The live environment then sees the decoded value right away. Works like a charm ✨✨ # How we chose our new frontend stack Source: https://blog.fortrabbit.com/our-new-frontend-stack Created: 2024-05-17 Author: Frank Lämmer Tags: webdev > So many options - React, Svelte, Vue, Nuxt, htmx, Interia, Livewire. What to choose for our new web properties? We are currently building a [new platform](https://new.fortrabbit.com) version (big rewrite). This includes our customer facing web properties: dashboard (hosting control panel), marketing page, docs and a blog. As a PHP hosting service we were curious to dog-food ourselves a new PHP-friendly frontend tech stack. This is what we have now and why. Our current web properties are already a decade old. They run as independent applications. Web, blog and docs are based on the Slim framework. The hosting dashboard is made with Laravel. It talks to a private API, also based on Laravel. I enjoyed using the powerful [Twig templating](https://twig.symfony.com/) engine across those properties. jQuery was used for interactivity and I created a global CSS stylesheet to be linked from all websites to align the visual appearance. Obviously in 2022 (when we started the new platform), we would do things a bit differently. At first we looked at a middleware solution between frontend and PHP. [Livewire](https://livewire.laravel.com/) (by Caleb Porzio) was just getting more integrated in the Laravel eco system. Although sexy, conceptually [Intertia.js](https://inertiajs.com/) (by Jonathan Reinink) was closer to our philosophy. We already had build a dashboard click dummy built in [Nuxt.js](https://nuxt.com/) (as a convenience layer for Vue.js). Originally we planned to start from scratch for the real thing with an eye on Svelte, maybe HTMX and raw web components. But we realised that Nuxt.js was actually matching our requirements and it was easier to just iterate on the existing code base from the dummy. The [Nuxt Content](https://content.nuxt.com/) extension serves the markdown files for the blog and the docs. The dashboard is a SPA, while the other websites will be pre-rendered. The code for our web properties now lives in a mono repo, handled with `pnpm`. The Vue components library is shared between the different projects. We tried [Storybook](https://storybook.js.org/) and [Histoire](https://histoire.dev/) to build and test our components in isolation. But I kept iterating on the components within their original context so the stories got outdated quickly. So we ditched that idea for now. We also swapped my [home-brew CSS solution Teutonic in favor for Tailwind](https://medium.com/teutonic-css/retiring-my-own-little-css-framework-e0a130ca2a33). I am still not sure if that is really a win, but maybe that's just my hurt ego. Later down the line we also decided to have the frontend talk to the backend API directly, instead of an additional PHP layer (Interia.js). For the API we flirted with GraphQL for a second but then quickly turned back to build a classical REST API. This is our PHP layer finally. It's build with the [API Platform](https://api-platform.com/) (Symfony world). It took me a while to adapt to some of the modern paradigms. I sometimes miss my old simple tech. But maybe that's just because I am getting old. A Single Page Application is nice, but loading traditional pages rendered by the PHP server from a monolith application served us well for a long time. Having customer facing technology separated from backend logic is a good separation of concerns. Yet separated code bases in different programming languages are more complex. We have more specific domain knowledge now. # New status page Source: https://blog.fortrabbit.com/our-new-status-page Created: 2014-09-02 Author: Frank Lämmer Tags: chronicles > status.fortrabbit.com becomes the official channel for scheduled maintenance and incidents, with mail, SMS and RSS subscriptions. ## status.fortrabbit.com We finally have a status page: [status.fortrabbit.com](http://status.fortrabbit.com) — an official channel were we communicate about scheduled maintenances and unscheduled downtimes (aka incidents). You can subscribe to this by mail, SMS or RSS. ### Our proccess Maybe you are thinking about a status page for your startup as well? Here is our journey (no relations). **tl;dr** We actually wanted to build something really cool ourselves but we finally ended up using a SaaS for now. First we checked what other PaaS and hosting companies were doing. Well, you find all kind of things in this space: from tumblr-blogs, to wordpress-blogs (not so bad!), to twitter-hacks, to simple-lists, to really-fancy-looking-custom-made-futuristic-designs. The first we have learned is that a status page is not so much about real time metrics and automatic system status aggregation, **a status page is mostly about communication from human to human**. One concern is of course that our status page must be up, even when the whole system is down and also when AWS is down. The open source solution [stashboard](http://www.stashboard.org/) from Twilio is an obvious candidate, as it runs on the Google App Engine Cloud. It's free, easy to setup and skin. However we were missing some features, adding means a lot of hacking and the repo looks a bit neglected. Developer hybris: building something on our own? Hm when should it be done 2015? Well then let's have a look at the commercial solutions, Statuspage as a Service. We've checked out [StatusHub](https://statushub.io/), [Status.io](http://status.io) and [Statuspage.io](https://www.statuspage.io/) and settled with the last one from Scott, Steve and Danny for now. It's mixed feelings. $80 bucks monthly or even more for something you can hack together in one or two days is pricey — maybe too much hype?. But some of the ideas/concepts/details are really nice and exactly the way they should be. So that's it for now, i hope not to see the system an action too soon. Things will go down one day for sure. # Vendor locked-in buzz Source: https://blog.fortrabbit.com/paas-vendor-locked-in-buzz Created: 2012-07-30 Author: Frank Lämmer Tags: opinion > How locked in is a website to its hosting provider, and does portability across clouds mean anything in practice for a PHP app? Apple, Microsoft, the wireless carrier and your razor blade supplier: They all lock you in - in a walled garden. Now, how dependent are you from your web-host? Lucas Carlson, founder of AppFog claimed that he has escaped vendor prison. His new platform runs on multiple cloud infrastructures. So the customer can choose on which infrastructure his project should be hosted on. Other PaaS providers also have a "No locked-in" icon and copy-text on their homepage. But what does that mean? You are unsatisfied with your web-hosting provider. So you want to leave. What are the real obstacles to overcome? ### Legal locked-in The contract with your old web-host says you can get out by the end of the period - usually a year. A letter on a dead tree with your original signature sent at least two months before is expected. New cloud platforms are all made by very nice people. Of course they would never lock you in with their terms. You can get out ad-hoc or at least at the end of the current month. ### Technical locked-in Imagine a host or cloud provider with a proprietary deployment method. Your app life cycle management totally relies on a special solution only offered by this vendor. To move over to another provider you need to adjust your whole work-flow. Google App Engine is a service with a custom own API. Some people don't like that. See [this question](http://news.ycombinator.com/item?id=2947577) on Hacker News. ### Data locked-in Let's say you have a social photo community with a few hundred thousand photos online. Or you are a small company with 10 employees. Each employee has an IMAP mailbox. Or you are an agency maintaining some hundred wordpress installations. How can you actually move this data? ### Résumé Cloud Vendor Lock-In is a buzz word nowadays. I totally agree with the folks on the [Gigaom panel](http://gigaom.com/cloud/vendor-lock-in-and-the-challenge-to-platform-as-a-service/), the technical limitation to one specific API is not the only problem. Compared to old school web hosts cloud IaaS and Paas providers are better: At least the terms of service allow a customer to leave. I think in reality customers don't want to change their Host, or PaaS, or underlying Infrastructure that often. Our Hosting experience shows us that customers just stick to what they got. They often forget about websites and projects and just pay for it. Sometimes I even help our clients to clean up their hosting stuff. I guess that's the fitness studio effect: You pay for membership, but you never show up. Technology might change quickly, will people change as well? #### Further reading * [Joe McKendrick on Cloud Vendor Lock-In](http://www.forbes.com/sites/joemckendrick/2011/11/20/cloud-computings-vendor-lock-in-problem-why-the-industry-is-taking-a-step-backwards/) # PHP 5.5 and improved deployment Source: https://blog.fortrabbit.com/php-5-5-and-improved-deployment Created: 2014-03-13 Author: Ulrich Kautz Tags: changelog > PHP 5.5 arrives with OPcache and optional APCu, alongside deployment improvements that make future platform upgrades quicker. ## A few updates Just so you can see that we don't stand still. Our recent [upgrade](/new-year-cleanup-maintenance) allows us to integrate new features faster and patch in upgrades with far less effort. So, not only to prove the point, we (finally!) make PHP 5.5 available, of course with [OPcache](http://de1.php.net/opcache) and optional [APCu](https://github.com/krakjoe/apcu). And we've added some new features to the deployment file. ## PHP 5.5 Well, you probably have heard all about it. It's not exactly new anymore. A complete list can be found [here](http://php.net/migration55.new-features). With OPcache and APCu the stats in the dashboard have changed. In a follow up article we will go into depth about how to use them best. For those who haven't heard about 5.5, here are quick teaser about two of the new features: ### Generators via yield You must simply love `yield` \- if you had ever implemented an [Iterator](http://de2.php.net/manual/en/class.iterator.php). A very basic example: ```php class MyModel() { // .. function someItems() { $items = $this->db->query(/* .. */); foreach ($items as $item) { yield $item; } } } // somewhere else foreach ($model->someItems() as $item) { echo "$item\n"; } ``` Read all about it [here](http://php.net/manual/en/language.generators.php). ### finally in Exceptions Finally there is `finally`, as you might know from lot's of other languages. ```php $foo = new Foo(); try { $foo->connect(); $foo->do(); } catch (\FooException $e) { echo "No joy: $e\n"; } finally { $foo->disconnect(); } ``` ## Deployment file upgrade If you haven't heard about our [deployment file](http://fortrabbit.com/docs/in-depth/deployment-file), check it out now! It's worth a look! ### Pre deploy scripts With the deployment file, you already can run post deploy scripts. With this upgrade, we added the capability to run pre deploy scripts as well. Here a hands-on example to safe-guard the deployment, in cause you do a lot of composer upgrades. #### ~/htdocs/deploy.php ```php if (2 !== count($argv)) { die("Missing deployment mode"); } $deploymentMode = $argv[1]; $htdocsFolder = getenv("HOME") . "/htdocs"; $htaccess = "$htdocsFolder/.htaccess"; $maintenancHtaccess = "$htaccess-maintenance"; $liveHtaccess = "$htaccess-live"; switch ($deploymentMode) { case 'pre': if (file_exists($maintenancHtaccess)) { rename($maintenancHtaccess, $htaccess); } break; case 'post': if (file_exists($liveHtaccess)) { rename($liveHtaccess, $htaccess); } break; } ``` #### ~/htdocs/fortrabbit.yml ```yml --- pre-deploy: script: deploy.php args: - pre post-deploy: script: deploy.php args: - post ``` ### Support for Composer source Until now, we enforced `\--prefer-dist` mode, which simply was faster on average (bandwidth is not an issue). However, in some cases `\--prefer-source` makes sense and can be faster. You can enable it now: #### ~/htdocs/fortrabbit.yml ```php --- composer: mode: always method: install prefer-source: 1 ``` If you already have a `vendor/` folder with existing packages, which were installed previously (using `\--prefer-dist`), than you need to remove the `vendor/` folder manually (SSH/SFTP) - if you want to use sources. ## More coming Soon we'll be making the (most requested) [New Relic extension](http://www.fortrabbit.com/feature/new-relic-support) available. We're rethinking our current testing/free plan to make it more available and clearer in it's purpose. More about that in the next days. Also, we're deep into our [new Dashboard](http://www.fortrabbit.com/feature/enhanced-dashboard), which will be just awesome. And we [heard you](http://www.fortrabbit.com/feature/hhvm-support) about HHVM. We're not entirely sure if we're integrating it with the old dashboard (there are completely different options and we don't like to work with the old dashboard anymore..) or whether we'll launch HHVM together with the new dashboard. And then there is a new App type upcoming, which will feature far greater performance and availability. Stay tuned! # PHP 7.1 is slowly fading out Source: https://blog.fortrabbit.com/php-71-fade-out Created: 2019-09-25 Author: Frank Lämmer Tags: changelog > Security support for PHP 7.1 ends in December 2019. The five-minute upgrade path, and what to check before switching production. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. [ Updated: 2019-12-20 ] ## Simple update **In a hurry?** Just change the PHP version in production like so: 1. In the [fortrabbit Dashboard](https://dashboard.fortrabbit.com/) 2. navigate to the App and then click on Settings > PHP 3. Change to a newer PHP version and hit "save". 4. Check if your website is still working after a few minutes. 5. You can safely switch back the version if it doesn't work (see below). ## Advanced update If the above procedure is breaking your website or you don't want to risk your production environment, here is a better, more sophisticated way: 1. Update your local development environment to make sure everything works 2. Push changes 3. Change PHP version with our Dashboard (like described above) Please see our old [PHP upgrade path](/php-upgrade-path) article, it was written for an older PHP version upgrade, but the steps are basically the same. ## Run down We will force-update all Apps still running on `PHP 7.1` to `PHP 7.2` on the **13th of January 2020**. ## Grace period You will still be able to switch back your App to `PHP 7.1` with our Dashboard for an extended period of time — the grace period. You can also ask us! to exclude certain of your Apps (please include the App names) from the switch right away, so no switch will happen on the 13th of Jan. We plan to support the deprecated PHP version for one more month at least. The final switch off is planned to happen with the next PHP updates in a few months. We will announce that in our usual communication channels - [status.fortrabbit.com](https://status.fortrabbit.com). There probably will be no extra mailings. We reserve the right to do a force-update to PHP 7.2 at any time, in case serious security issues get revealed during the grace period. With the final switch, we will remove the PHP 7.1 binary so it will not be possible to switch back then any more. Please reach with questions and feedback. We are listening and happy to help. ## Potentially asked questions ### Which software version do I need to update to? Sometimes it is difficult to find the time to upgrade an old project. Maybe you can come by with just a patch update without too much hassle? This is difficult to answer, projects rarely specify if their older releases support PHP 7.2, also there are plugins and custom code. But here are some we know of. The following versions refer to major version, upgraded to the latest minor and patch releases (major.minor.patch). * **Laravel**: version ~~4 and~~ 5 will run on PHP 7.2 * **Symfony**: version 2, 3 and 4 will run on PHP 7.2 * **Craft CMS**: version 2 and 3 will run on PHP 7.2 * **WordPress**: version 4 and 5 will run on PHP 7.2 ### To which PHP version shall I update? **Upgrade to PHP 7.3 if possible.** The lowest version you need to update now is to `PHP 7.2`, but there are only minor differences between `PHP 7.2` and `PHP 7.3`, it's likely that your App also runs on `PHP 7.3`, so try the bigger jump right away. ### Why we need to do this? **Sorry, PHP deadlines are not set by us, [see php.net](https://www.php.net/supported-versions.php).** We can not risk to run unsupported PHP versions much longer for security reasons. In other words: PHP 7.1 is now "dead": see [here](https://www.php.net/eol.php). This means that no security patch will be released for this version. We will not support `PHP 7.1` anymore, as we don't support `PHP 4`, for example. We are not alone to do this. This follows industry standards. ### Why we can't do it for you? **It's your code**, your website. You need to make sure that the project will run with a newer version of PHP. We can not do that for you. We don't know your software and the inner workings of it. Check our [support policies](https://www.fortrabbit.test/support-policy) again please. ### How can I test my code? Please check out our old [PHP testing article](/php-testing) highlighting strategies and tooling to test your code for issues. ### What about mcrypt? A prominent change from `PHP 7.1` to `PHP 7.2` is that the popular mcrypt extension was removed. See [php.net](https://www.php.net/manual/en/migration71.deprecated.php) for details. So you can not enable that extension any more here. With a framework or CMS that should not be your concern. It's either already on OpenSSL or a polyfill like [mcrypt_compat](https://github.com/phpseclib/mcrypt_compat) is used. ## Can you do the code updates for me? Sorry no. Please check our [support policy](https://www.fortrabbit.com/support-policy) one more time. ## Cheers Thanks for taking the time to keep your software up-to-date. Have a question? Don't hesitate to ask us right away! We can also offer you some discount for running two versions of your Apps side by side. # PHP 7.1 is here Source: https://blog.fortrabbit.com/php-71-released Created: 2017-02-15 Author: Ulrich Kautz Tags: changelog > PHP 7.1 becomes available for all Universal and Professional Apps, after a waiting period to rule out early release bugs. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. PHP 7.1 is now available for all Universal and Professional Apps. To learn more about the new language features [stop by Jeffrey's PHP 7.1 series](https://laracasts.com/series/whats-new-in-php-7-1). Before upgrade we refer you to the [official migration guide](http://php.net/manual/en/migration71.php) for an overview. In short: there are no major breaking changes we are aware of from 7.0 to 7.1. However, there are [minor changes which could break edge-cases](https://blog.pascal-martin.fr/post/php71-en-a-few-bc-breaks-and-conclusion.html). No worries, we do not automatic upgrade any App. You can upgrade at any with a click, though. Login to the Dashboard, go to your App > PHP and change the version. ![Choose version](/images/php-71-choose-version.png) There is no immediate need to so. We'll be supporting older PHP versions (5.6, 7.0) until their official end of life: - PHP 5.6: 2018-12-31 (LTS) - PHP 7.0: 2018-12-03 - PHP 7.1: 2019-12-01 You can find the official EoL dates always on [php.net](http://php.net/supported-versions.php). ## New extensions We also are happy to announce that [GnuPG](http://php.net/manual/en/book.gnupg.php), [igbinary](https://pecl.php.net/package/igbinary) and [GeoIP](http://php.net/manual/en/book.geoip.php) became available for both PHP 7.0 and 7.1. ## Caveat PHP 7.1 support is not complete. Phalcon 3 is [still missing](https://github.com/phalcon/cphalcon/issues/12055) and we hope it will become available with our next patch upgrade. So far, we advice to use Phalcon with PHP 7.0. # PHP 7.2 support to end soon Source: https://blog.fortrabbit.com/php-72-eol Created: 2020-11-11 Author: Frank Lämmer Tags: changelog > PHP 7.2 stops receiving security updates and support on fortrabbit ends. The quick upgrade route that works for most apps. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Simple update This is the simple way to update your App in 5 minutes. It should work for 90% of the Apps here: 1. Make sure the software you are using is up-to-date 2. In the [fortrabbit Dashboard](https://dashboard.fortrabbit.com/) 3. navigate to the App and then click on Settings > PHP 4. Change to a newer PHP version and hit "save". 5. Check if your website is still working after a few minutes. 6. You can safely switch back the version if it doesn't work (see below to continue). ## Advanced update If the above procedure is breaking your website or you don't want to risk your production environment, here is a better, more sophisticated way. 1. Update your local development environment to at least PHP 7.2 2. Update the software you are using locally (think `composer update`) 3. Push changes 4. Change PHP version with our Dashboard (as described above) Please see our old [PHP upgrade path](/php-upgrade-path) article; it was written for an older PHP version upgrade, but the steps are basically the same. Please also see the [official PHP 7.3 incompatible list](https://www.php.net/manual/en/migration73.incompatible.php). ## Run down We will force-update all Apps still running on `PHP 7.2` to `PHP 7.3` on the **13th of January 2021**. ## Grace period You will still be able to switch back your App to `PHP 7.2` with our Dashboard for an extended period of time after the first switch — this is what we consider the grace period. You can also ask us to exclude certain of your Apps (please include the App names) from the switch right away, so no switch will happen on the 13th of Jan. We plan to support the deprecated PHP version for one more month at least. The final switch off is planned to happen with the next PHP updates in a few months. We will announce that in our usual communication channels - [status.fortrabbit.com](https://status.fortrabbit.com). For Apps in grace period, there will probably be no extra mailings. We reserve the right to do a force-update to PHP 7.3 at any time, in case serious security issues get revealed during the grace period. With the final switch, we will remove the PHP 7.2 binary so it will not be possible to switch back then any more. Please reach out with questions and feedback. We are listening and happy to help. ## Potentially asked questions ### Which software version do I need to update to? Sometimes it is difficult to find the time to upgrade an old project. Maybe you can get by with just a patch update? This is difficult to answer, projects rarely specify if their older releases support PHP 7.2, and there are plugins and custom code to consider. ### To which PHP version shall I update? **Upgrade to PHP 7.4 if possible.** The lowest version you need to update to now is `PHP 7.3`, but since there are only minor differences between `PHP 7.3` and `PHP 7.4`, it's likely that your App also runs on `PHP 7.4`. So try the bigger jump right away. ### Why do we need to do this? **Sorry, PHP deadlines are not set by us, [see php.net](https://www.php.net/supported-versions.php).** We cannot risk running unsupported PHP versions much longer for security reasons. See also the [EOL document here](https://www.php.net/eol.php). ### Why can't we do the required updates for you? **It's your code**, your website. You need to make sure that the project will run with a newer version of PHP. We cannot do that for you. We don't know your software and the inner workings of it. Check our [support policies](https://www.fortrabbit.test/support-policy). ### How can I test my code? Please check out our old [PHP testing article](/php-testing), highlighting strategies and tooling to test your code. ## Cheers Thanks for taking the time to keep your software up-to-date. Have a question? Don't hesitate to ask us right away! We can also offer you a discount for running two versions of your Apps side by side. # PHP 7.3 support to end soon Source: https://blog.fortrabbit.com/php-73-eol Created: 2022-01-19 16:03:34 Author: Frank Lämmer Tags: changelog > PHP 7.3 reaches end of life and gets switched to 7.4 on 13 April 2022. What to test before that date, and how to move earlier. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Update 2022-03-21 The final fore switch from PHP 7.3 to PHP 7.4 is now planned for 13th of April 2022. This will mark the end of the grace period. It will not be possible to switch back after that. ## Simple update This is the simple way to update your App in 5 minutes. It should work for 90% of the Apps here: 1. Make sure the software you are using is up-to-date 2. In the [fortrabbit Dashboard](https://dashboard.fortrabbit.com/) 3. navigate to the App and then click on Settings > PHP 4. Change to a newer PHP version and hit "save" 5. Check if your website is still working after a few minutes 6. You can safely switch back the version if it doesn't work (see below to continue) ## Advanced update If the above procedure is breaking your website or you don't want to risk your production environment, here is a better, more sophisticated way: 1. Update your local development environment to at least `PHP 7.4` 2. Update the software you are using locally (think `composer update`) 3. Push changes 4. Change PHP version with our Dashboard (as described above) Please see our old [PHP upgrade path](/php-upgrade-path) article; it was written for an older PHP version upgrade, but the steps are basically the same. Please also see the [official PHP 7.3 incompatible list](https://www.php.net/manual/en/migration73.incompatible.php). ## Run down We plan to force-update all Apps still running on `PHP 7.3` to `PHP 7.3` on the **21st of January 2022** (date is subject to change). ## Grace period You will still be able to switch back your App to `PHP 7.3` with our Dashboard for an extended period of time after the first switch — this is what we consider the grace period. You can also ask us to exclude certain of your Apps (please include the App names) from the switch right away, so no switch will happen initially. We plan to support the deprecated PHP version for one more month at least. The final switch off is planned to happen about a month later. We will announce that in our usual communication channels - [status.fortrabbit.com](https://status.fortrabbit.com). For Apps in grace period, there will probably be no extra mailings. We reserve the right to do a force-update to PHP 7.4 at any time, in case serious security issues get revealed during the grace period. With the final switch, we will remove the PHP 7.3 binary so it will not be possible to switch back then any more. Please reach out with questions and feedback. We are listening and happy to help. ## Potentially asked questions ### Which software version do I need to update to? Sometimes it is difficult to find the time to upgrade an old project. Maybe you can get by with just a patch update? This is difficult to answer, projects rarely specify if their older releases support PHP 7.3, and there are plugins and custom code to consider. ### To which PHP version shall I update? **Upgrade to PHP 7.4 if possible.** The lowest version you need to update to now is `PHP 7.3`, but since there are only minor differences between `PHP 7.3` and `PHP 7.4`, it's likely that your App also runs on `PHP 7.4`. So try the bigger jump right away. ### Why do we need to do this? **Sorry, PHP deadlines are not set by us, [see php.net](https://www.php.net/supported-versions.php).** We cannot risk running unsupported PHP versions much longer for security reasons. See also the [EOL document here](https://www.php.net/eol.php). ### Why can't we do the required updates for you? **It's your code**, your website. You need to make sure that the project will run with a newer version of PHP. We cannot do that for you. We don't know your software and the inner workings of it. Check our [support policies](https://www.fortrabbit.test/support-policy). ### How can I test my code? Please check out our old [PHP testing article](/php-testing), highlighting strategies and tooling to test your code. ## Cheers Thanks for taking the time to keep your software up-to-date. Have a question? Don't hesitate to ask us right away! We can also offer you a discount for running two versions of your Apps side by side. # PHP 7.4 support to end some day Source: https://blog.fortrabbit.com/php-74-eol Created: 2022-10-14 Author: Frank Lämmer Tags: changelog > PHP 7.4 reaches end of life. Why PHP 8 is worth the move — speed, active maintenance, new features — and how to get there. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Why upgrade to PHP 8? - It's faster - It's actively maintained - It has new features - It's stable, version 8.1 is out - Current software will require this ## When to upgrade to PHP 8? Now is a good time. Our [PHP update policies](https://www.fortrabbit.com/update-policies#new-php-versions) state that we will upgrade the PHP version right after official security support ends. In the past we often allowed some extra time and an additional grace for late clients to stay on an older PHP version longer. Since this is a major version upgrade and there are many potential breaking changes from PHP 7.4 to PHP 8 we decided to give us as much time as possible. ## When is the latest I will have to upgrade to PHP 8 at fortrabbit? We plan to support PHP 7.4 until mid 2023 or longer. We will inform our clients individually ahead of time. ## What are the lowest software versions with support for PHP 8? In general we advise you to use the latest software versions available. This is especially true for your framework and CMS system. But upgrading to new major versions can be a hassle - maybe you want to know if it's possible to upgrade to another minor release of your software. ### Craft CMS The current Craft CMS major version is 4. Craft CMS 2 does not support PHP 8. We still have a couple of Craft 2 installations around. Here is our [article to update from Craft 2 to Craft 3](https://help.fortrabbit.com/craft-2-3-upgrade). ### Laravel The current major Laravel version is 9. Laravel 6 supports PHP 8. Older versions do not. ### WordPress The current major WordPress version is 6. WordPress 5.6 - 5.9 has “beta support” for PHP 8. See the [official WordPress PHP Compatibility and WordPress Versions](https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/) page. ## How to upgrade from PHP 7.4 to PHP 8? Please have a look at our [general PHP version upgrade help article](https://help.fortrabbit.com/php-version-upgrade). ## Can you (the web host) do the update for me? Sorry no. It's your website and your code. We don't know about it and won't touch it. Please get in touch with us if you have a concrete technical question. ## Where can I find more details? - [Upgrading a Project to PHP 8.0](https://medium.com/oro-development/upgrade-to-php-8-64f770ae4479) by Andrii Yatsenko with useful tips - [Official PHP documentation](https://www.php.net/manual/en/migration80.php) on the migration path to PHP 8 # PHP 7.4 and other updates Source: https://blog.fortrabbit.com/php-74-update Created: 2020-03-27 Author: Frank Lämmer Tags: changelog > The platform update bringing PHP 7.4 and a set of extension bumps, with version numbers, timing and expected downtime. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. **Last update:** 1st of April 2020, 12:09 CET ## Run down The updates will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### US region **Tuesday, 31st of March 2020** US maintenance window starts at 08:00 AM - UTC 04:00 AM - in NYC 10:00 AM - in Berlin 01:00 AM - in SF

Post Mortem for updates in US

While doing the planned maintenance we encountered unexpected technical problems: A small number of Nodes was affected by high load. So far, we have not been able to fully identify the root issue. We believe it's related to the underlying file system of the containers: BTRFS. The high load caused some on/off behaviour for affected Apps. We mitigated the issue by replacing the Nodes. ~250 Apps have been moved. The downtime per App was individual. Up to 40 minutes downtime for the mitigation. The IP of the Apps in question changed. A "re-deploy" — latest contents of the Git repo got re-applied — was triggered for those Apps. This (actually a feature) caused some additional trouble for clients who have started to work with Git deployment but later switched to SSH/SFTP workflows. We have been able to resolve most (not all) of these cases by applying backups. Please contact us if you still have trouble with you App, likely we can help you. ### Europe region Due to the problems faced in US, we have postponed the roll-out in EU to: **Wednesday, 31st of March 2020** EU maintenance window starts at 16:00 PM - UTC 18:00 PM - in Berlin ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 7.4 runtime for all their Apps. Here is the complete list of client facing changes: ### PHP versions - PHP74 (none) > 7.4.4 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - PHP73 (7.3.10) > 7.3.16 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) - PHP72 (7.2.23) > 7.2.29 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_2) - PHP71 (7.1.32) > 7.1.33 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_1) This is the last time update for PHP 7.1 before we'll drop it. Please update now. See the officially [supported PHP versions](https://www.php.net/supported-versions.php) and our [PHP 7.1 EOL guide](https://blog.fortrabbit.com/php-71-fade-out). ### Extensions installed from pecl - apcu (5.1.17) > 5.1.18 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - geoip (1.1.1) - [changelog](https://pecl.php.net/package-changelog.php?package=geoip) - igbinary (3.0.1) > 3.1.2 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.4.4) - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - mongodb (1.5.5) > 1.7.4 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - oauth (2.0.3) > 2.0.5 - [changelog](https://pecl.php.net/package-changelog.php?package=oauth) - redis (4.3.0) > 5.2.1 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - libsodium (1.0.7) - [changelog](https://pecl.php.net/package-changelog.php?package=libsodium) - Only for PHP 7.1, later versions include this extension in core. - ssh2 (1.2) - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) - sqlsrv (5.6.1) > DROPPED - [changelog](https://pecl.php.net/package-changelog.php?package=sqlsrv) - pdo_sqlsrv (5.6.1) > DROPPED- [changelog](https://pecl.php.net/package-changelog.php?package=pdo_sqlsrv) - yaml (2.0.4) - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) ### Custom build extensions - memcached (3.1.3) > 3.1.5 - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - libmemcached (1.0.18) - with 2 patches applied - [changelog](https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/ChangeLog) - phalcon (3.4.4) > 3.4.5 - [release notes](https://github.com/phalcon/cphalcon/releases) - We will not upgrade to phalcon 4. Phalcon 3 will not support PHP 7.4. So no phalcon with fortrabbit for php 7.4. [https://github.com/phalcon/cphalcon/issues/14574#issuecomment-560303839](https://github.com/phalcon/cphalcon/issues/14574#issuecomment-560303839) ### 3rd party extensions - blackfire php probe (1.27.1) > 1.31.0 - blackfire agent (1.27.4) > 1.32.0 - [changelog](https://packages.blackfire.io/binaries/blackfire-agent/1.27.4/CHANGELOG) - newrelic php probe (8.7.0.242) > 9.6.1.256 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) - newrelic agent (8.7.0.242) > 9.6.1.256 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ### Updated command line tools - `composer` (1.8.5) > 1.10.1 - [changelog](https://github.com/composer/composer/blob/master/CHANGELOG.md) - `convert` ImageMagick (7.0.8-66) > 7.0.10-1 - [changelog](https://www.imagemagick.org/script/changelog.php) # PHP 8.0.12 Source: https://blog.fortrabbit.com/php-8-0-12-update Created: 2021-11-11 Author: Frank Lämmer Tags: changelog > The platform update rolling out PHP 8.0.12 to all Uni and Pro apps, with the full version list and the downtime to expect. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down As usual: This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### US region On **Wednesday, 17th of November 2021** the maintenance window starts at 10:00 AM - Berlin 09:00 AM - UTC 04:00 AM - NYC 01:00 AM - SF ### Europe region On **Thursday, 18th of November 2021** the maintenance window starts at 07:30 PM - Berlin 06:30 PM - UTC ## Client facing changes Here is the complete list of client facing changes: - PHP80 (8.0.2) > 8.0.12 - [changelog](https://www.php.net/ChangeLog-8.php) - PHP74 (7.4.15) > 7.4.25 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - PHP73 (7.3.27) > 7.3.32 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) ## PHP Extensions ### Installed from pecl - apcu (5.1.19) > 5.1.21 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - igbinary (3.2.1) > 3.2.6 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.4.4 + [448c1cd0](https://github.com/Imagick/imagick/commit/448c1cd0d58ba2838b9b6dff71c9b7e70a401b90)) > 3.5.1 - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.0.10-1) > 7.0.10-62 - [changelog](https://imagemagick.org/script/changelog.php) - gnupg (1.5.0-rc1) > 1.5.0 - [changelog](https://pecl.php.net/package-changelog.php?package=gnupg) - mongodb (1.9.0) > 1.11.1 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - redis (5.3.3) > 5.3.4 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - yaml (2.2.1) > 2.2.2 - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) - ssh2 (1.2 + [93265d71b](https://github.com/php/pecl-networking-ssh2/commit/93265d71bdeb23350e8320126c7949ed791310df)) > 1.3.1 - [changelo](https://pecl.php.net/package-changelog.php?package=ssh2) ### 3rd party extensions - blackfire php probe (1.49.1) > 1.69.0 - [list of current versions](https://blackfire.io/docs/up-and-running/update) - blackfire agent (1.46.0) > 1.50.0 - [changelog](https://packages.blackfire.io/binaries/blackfire-agent/1.46.0/CHANGELOG) - newrelic php probe (9.16.0.295) > 9.18.1.303 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) - newrelic agent (9.16.0.295) > 9.18.1.303 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ## Older Craft CMS versions need to be updated During testing for this release we have noticed an incompatibility (signature change) of the imagick extension and older versions of Craft CMS which use an unpatched version of `pixelandtonic/imagine`. **Update your Craft CMS if your version is still on 3.4 or lower.** Update to at least version 3.5. The current version (time of this writing) of Craft CMS is 3.7.20. See our [Craft CMS update guide](https://help.fortrabbit.com/craft-3-update) on how to do that best. ### Further details Version `1.2.4.2` of `pixelandtonic/imagine` includes a patch. All previous versions will break certain image related functionality. If you use a newer version of Craft CMS (3.5 - 3.7) and update it on a regular basis, the patch is probably included already. ### Verify the version and update with Composer In general we advice to use the Craft CLI (`./craft update all`) to update your local Craft CMS before deploying the new version to fortrabbit. Here are detailed instructions on how to verify that you are already on the correct version and get it up-to-date with Composer (locally first). ```shell composer info pixelandtonic/imagine | grep versions ``` 1. Version: 1.2.4.2 > Nothing to do 🥳 2. Version: 1.2.4.0 or 1.2.4.1 > run `composer update pixelandtonic/imagine -w` 3. Version: 1.2.2.0 or 1.2.2.1 > run `composer require pixelandtonic/imagine:"1.2.4.2 as 1.2.2.1"` After successfully updating the package, commit and push the updated composer.json/lock to your App. # PHP 8 Source: https://blog.fortrabbit.com/php-8-update Created: 2021-02-22 Author: Frank Lämmer Tags: changelog > PHP 8 rolls out across the fortrabbit platform. The full list of versions and extensions, plus timing and expected downtime. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down As usual: This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### US region On **Wednesday, 24th of February 2021** the maintenance window starts at 10:30 AM - Berlin 09:30 AM - UTC 04:30 AM - NYC 01:30 AM - SF ### Europe region On **Thursday, 25th of February 2021** the maintenance window starts at 19:00 PM - Berlin 18:00 PM - UTC ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 8 runtime for all their Apps. PHP 8 will become default for new Apps as well. Please mind that we will also drop support for PHP 7.2 with this update. Here is the complete list of client facing changes: ## PHP versions - PHP80 (8.0.2) - [changelog](https://www.php.net/ChangeLog-8.php) - PHP74 (7.4.4) > 7.4.15 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - PHP73 (7.3.16) > 7.3.27 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) - PHP72 (7.2.29) > DROPPED [php.net/supported-versions](https://www.php.net/supported-versions.php) ## Main services - Apache httpd (2.4.43) > 2.4.46 - [changelog](https://downloads.apache.org/httpd/CHANGES_2.4) ## PHP Extensions ### Installed from pecl - apcu (5.1.18) > 5.1.19 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - igbinary (3.1.2) > 3.2.1 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - mongodb (1.7.4) > 1.9.0 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - oauth (2.0.5) > 2.0.7 - [changelog](https://pecl.php.net/package-changelog.php?package=oauth) - redis (5.2.1) > 5.3.3 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - yaml (2.0.4) > 2.2.1 - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) ### Custom built extensions - geoip (1.1.1) - with php8 patch applied - [changelog](https://pecl.php.net/package-changelog.php?package=geoip) - gnupg (1.4.0) > 1.5.0-rc1 - [changelog](https://pecl.php.net/package-changelog.php?package=gnupg) - imagick (3.4.4) > [448c1cd0](https://github.com/Imagick/imagick/commit/448c1cd0d58ba2838b9b6dff71c9b7e70a401b90) - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.0.10-1) > 7.0.10-62 - [changelog](https://imagemagick.org/script/changelog.php) - memcached (3.1.5) - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - libmemcached (1.0.18) - with 2 patches applied - [changelog](https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/ChangeLog) - phalcon (3.4.5) - [release notes](https://github.com/phalcon/cphalcon/releases) - We are slowly phasing out support for phalcon and it is not included with php 7.4 or 8.0 on fortrabbit. - ssh2 (1.2) > [93265d71b](https://github.com/php/pecl-networking-ssh2/commit/93265d71bdeb23350e8320126c7949ed791310df) - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) ### 3rd party extensions - blackfire php probe (1.31.0) > 1.49.1 - [list of current versions](https://blackfire.io/docs/up-and-running/update) - blackfire agent (1.32.0) > 1.46.0 - [changelog](https://packages.blackfire.io/binaries/blackfire-agent/1.46.0/CHANGELOG) - newrelic php probe (9.6.1.256) > 9.16.0.295 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) - newrelic agent (9.6.1.256) > 9.16.0.295 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) # PHP 8.1 Source: https://blog.fortrabbit.com/php-81-update Created: 2022-03-14 Author: Frank Lämmer Tags: changelog > PHP 8.1 rolls out to all Uni and Pro apps. The version and extension numbers, the schedule, and the downtime to expect. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down Business as usual: This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### Europe region On **Wednesday, 16th of March 2022** the maintenance window starts at 19:00 PM - Berlin 18:00 PM - UTC ### US region On **Thursday, 17th of March 2022** the maintenance window starts at 10:00 AM - Berlin 09:00 AM - UTC 04:00 AM - NYC 01:00 AM - SF ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 8.1 runtime for all their Apps. PHP 8.1 will become default for new Apps soon. We will also drop support for [PHP 7.3 soon](/php-73-eol). Here is the complete list of client facing changes: ## PHP versions [https://www.php.net/supported-versions.php](https://www.php.net/supported-versions.php) - PHP81 (8.1.3) - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1) - PHP80 (8.0.12) > 8.0.16 - [changelog](https://www.php.net/ChangeLog-8.php) - PHP74 (7.4.25) > 7.4.28 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - PHP73 (7.3.32) > 7.3.33 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) - soon to be removed! [See](/php-73-eol) ## PHP Extensions ### Installed from pecl - apcu (5.1.21) - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - igbinary (3.2.6) > 3.2.7 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.5.1) > 3.7.0 - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.0.10-62) > 7.1.0-26 - [changelog](https://imagemagick.org/script/changelog.php) - gnupg (1.5.0) > 1.5.1 - [changelog](https://pecl.php.net/package-changelog.php?package=gnupg) - mongodb (1.11.1) > 1.12.1 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - oauth (2.0.7) - [changelog](https://pecl.php.net/package-changelog.php?package=oauth) - redis (5.3.4) > 5.3.7 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - yaml (2.2.2) - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) - ssh2 (1.3.1) - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) ### Custom built extensions - geoip (1.1.1) - with php8 patch applied - [changelog](https://pecl.php.net/package-changelog.php?package=geoip) - (not available for PHP 8.1) - memcached (3.1.5) - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - libmemcached (1.0.18) - with 2 patches applied - [changelog](https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/ChangeLog) - phalcon (3.4.5) > 4.1.3 - [release notes](https://github.com/phalcon/cphalcon/releases) ### 3rd party extensions - blackfire php probe (1.49.1) > 1.75.0 - [list of current versions](https://blackfire.io/docs/up-and-running/update) - blackfire agent (1.46.0) > 2.6.0 - newrelic php probe and agent (9.18.1.303) > 9.19.0.309 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) # PHP 8.2 Source: https://blog.fortrabbit.com/php-82-update Created: 2023-04-12 Author: Frank Lämmer Tags: changelog > PHP 8.2 rolls out across the platform. The complete version list for PHP and its extensions, with timing and expected downtime. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down Business as usual: This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### Europe region On **Monday, 27th of March 2023** the maintenance window starts at 18:00 PM - Berlin 16:00 PM - UTC ### US region On **Wednesday, 29th of March 2023** the maintenance window starts at 09:00 AM - Berlin 07:00 AM - UTC ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 8.2 runtime for all their Apps. PHP 8.2 will become default for new Apps soon. We will also drop support for [PHP 7.4 someday](/php-74-eol). Here is the complete list of client facing changes: ## PHP versions [https://www.php.net/supported-versions.php](https://www.php.net/supported-versions.php) - PHP82 (8.2.4) - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_2) - PHP81 (8.1.3) → 8.1.17- [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1) - PHP80 (8.0.16) → 8.0.28 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_0) - PHP74 (7.4.28) → 7.4.33 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - to be removed one day! [See](/php-74-eol) ## PHP Extensions ### Installed from pecl (new versions only) - apcu (5.1.21) → 5.1.22 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - igbinary (3.2.7) → 3.2.14 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.5.1) → 3.7.0 - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.1.0-26) → 7.1.1-3 - [changelog](https://imagemagick.org/script/changelog.php) - mongodb (1.12.1) → 1.15.1 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - yaml (2.2.2) → 2.2.3 - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) ### Custom built extensions - memcached (3.1.5) → 3.2.0 - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - ~~libmemcached (1.0.18) - with 2 patches applied - [changelog](https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/ChangeLog)~~ - libmemcached-awesome (1.1.4) - [release notes](https://github.com/awesomized/libmemcached/releases) - phalcon5 (5.2.1) - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 8.0, 8.1, 8.2 ### 3rd party extensions - blackfire agent/client (2.6.0) > 2.14.0 - [changelog](https://packages.blackfire.io/binaries/blackfire/2.14.0/CHANGELOG) - blackfire php probe (1.76.0) > 1.86.4 - [list of current releases](https://blackfire.io/docs/up-and-running/update) - newrelic php probe and agent (9.19.0.309) > 10.7.0.319 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) # PHP 8.3 Source: https://blog.fortrabbit.com/php-83-update Created: 2024-03-20 10:36:54 Author: Frank Lämmer Tags: changelog > PHP 8.3 rolls out to all Uni and Pro apps. The version list for PHP and its extensions, the schedule and the downtime to expect. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down The same procedure as every year: This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 30 minutes. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Date and time ### US region On **Wednesday, 25th of March 2024** the maintenance window starts at 08:00 AM - Berlin 07:00 AM - UTC ### Europe region On **Monday, 25th of March 2024** the maintenance window starts at 18:00 PM - Berlin 17:00 PM - UTC ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 8.3 runtime for all their Apps. PHP 8.3 will become default for new Apps soon. ## PHP versions - PHP83 (8.3.4) - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_3) - PHP82 (8.2.8) → 8.2.17 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_2) - PHP81 (8.1.21) → 8.1.27 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1) - PHP80 (8.0.29) → 8.0.30 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_0) - EOL December 2023 - PHP74 (7.4.33) - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - EOL December 2022 (see below) ## Main services - Apache httpd (2.4.51) - [changelog](https://downloads.apache.org/httpd/CHANGES_2.4) - HAProxy Routing (1.9.15) - [changelog](http://www.haproxy.org/download/1.9/src/CHANGELOG) ## PHP Extensions ### Installed from pecl - apcu (5.1.22) → 5.1.23 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - gnupg (1.5.1) - [changelog](https://pecl.php.net/package-changelog.php?package=gnupg) - igbinary (3.2.14) → 3.2.15 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.7.0) - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.1.1-15) → 7.1.1-29 - [changelog](https://imagemagick.org/script/changelog.php) - mongodb (1.16.2) → 1.17.2 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - oauth (2.0.7) - [changelog](https://pecl.php.net/package-changelog.php?package=oauth) - redis (5.3.7) → 6.0.2 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - ssh2 (1.3.1) → 1.4.1 - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) - yaml (2.2.3) - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) ### Custom built extensions - geoip (1.1.1) - with php8 patch applied - [changelog](https://pecl.php.net/package-changelog.php?package=geoip) - (only available for PHP 7.4 and 8.0) - memcached (3.2.0) - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - libmemcached-awesome (1.1.4) - [release notes](https://github.com/awesomized/libmemcached/releases) - phalcon4 (4.1.2) - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 7.4 - psr (1.2.0) - [changelog](https://pecl.php.net/package-changelog.php?package=psr) - phalcon5 (5.3.0) → 5.6.2 - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 8.0, 8.1, 8.2, 8.3 ### 3rd party extensions - blackfire php probe (1.89.0) > 1.92.10 - [list of current releases](https://blackfire.io/docs/up-and-running/update) - blackfire agent/client (2.21.0) > 2.26.0 - [changelog](https://packages.blackfire.io/binaries/blackfire/2.26.0/CHANGELOG) - newrelic php probe and agent (10.11.0.3) > 10.18.0.8 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ## A note on PHP 7.4 (and PHP 8.0) EOL So far, we have been able to keep the unsupported versions PHP 7.4 and PHP 8.0 running well after their sell-by-date. There will be no updates, patches and security fixes from the PHP maintainers any more. Thus, these two PHP versions are provided from us at best effort. If a serious security issues comes to light, we will need to force update to the next PHP version with short notice. Please review your Apps with us, see what still runs on PHP 7.4 or PHP 8.0 and you are able upgrade. We know that it is painful and we feel you. We don't wan't to break your websites. We understand that there is often no time or budget to keep all projects updated. Yet, it is your duty as the maintaining developer to keep your software updated. ### Related - **[PHP version upgrade help article](https://help.fortrabbit.com/php-version-upgrade)** - [Supported PHP versions](https://www.php.net/supported-versions.php) - offical php.net website - [PHP 7.4 EOL announcement here](/php-74-eol) from October 2022 # PHP 8.4 Source: https://blog.fortrabbit.com/php-84-update Created: 2025-04-23 12:04:25 Author: Frank Lämmer Tags: changelog > PHP 8.4 rolls out across the fortrabbit platform. The full version list, the sequential update procedure and the expected downtime. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## Run down This platform update will impact all Apps (Uni and Pro). The expected downtime for App web delivery is up to 20 minutes, though we aim to minimize it to just a few minutes. Updates will be applied sequentially, App by App. For deployment services (Git, SSH, and SFTP), a maximum downtime of around 30 minutes is expected. Stay informed by checking our [status page](https://status.fortrabbit.com), where we will post regular updates throughout the process. ## Date and time ### US region On **Monday, 28th of April 2025** the maintenance window starts at 08:00 AM - Berlin 06:00 AM - UTC ### Europe region On **Monday, 28th of Aril 2025** the maintenance window starts at 18:00 PM - Berlin 16:00 PM - UTC ## Client facing changes When both regions are rolled out, clients will be able to select the PHP 8.4 runtime for all their Apps. PHP 8.4 will become default for new Apps soon after. ## PHP versions - PHP84 (8.4.6) NEW! - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_4) - PHP83 (8.3.8) → 8.3.20 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_3) - PHP82 (8.2.20) → 8.2.28 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_2) - PHP81 (8.1.29) → 8.1.32 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1) - PHP80 (8.0.30) - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_0) - EOL Dec 2023 - PHP74 (7.4.33) - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - EOL Dec 2022 ## Main services - Apache httpd (2.4.59) → 2.4.?? - [changelog](https://downloads.apache.org/httpd/CHANGES_2.4) - HAProxy Routing (2.2.31) - [changelog](http://www.haproxy.org/download/2.2/src/CHANGELOG) ## PHP Extensions ### Installed from pecl - apcu (5.1.23) → 5.1.24 - [changelog](https://pecl.php.net/package-changelog.php?package=apcu) - gnupg (1.5.1) → 1.5.2 - [changelog](https://pecl.php.net/package-changelog.php?package=gnupg) - igbinary (3.2.15) → 3.2.16 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.7.0) → 3.8.0 - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - ImageMagick library (7.1.1-33) → 7.1.1-47 - [changelog](https://imagemagick.org/script/changelog.php) - mongodb (1.19.3) → 1.20.1 for PHP 7.4, 8.0 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - mongodb (1.19.3) → 1.21.0 for PHP 8.1, 8.2, 8.3, 8.4 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - oauth (2.0.7) → 2.0.9 - [changelog](https://pecl.php.net/package-changelog.php?package=oauth) - redis (6.0.2) → 6.2.0 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - ssh2 (1.4.1) - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) - yaml (2.2.3) → 2.2.4 - [changelog](https://pecl.php.net/package-changelog.php?package=yaml) ### Custom built extensions - geoip (1.1.1) - with php8 patch applied - [changelog](https://pecl.php.net/package-changelog.php?package=geoip) - (only available for PHP 7.4 and 8.0) - memcached (3.2.0) → 3.3.0 - [release notes](https://github.com/php-memcached-dev/php-memcached/releases) - ~~libmemcached (1.0.18) - with 2 patches applied - [changelog](https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/ChangeLog)~~ - libmemcached-awesome (1.1.4) - [release notes](https://github.com/awesomized/libmemcached/releases) - phalcon4 (4.1.2) - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 7.4 - psr (1.2.0) - [changelog](https://pecl.php.net/package-changelog.php?package=psr) - phalcon5 (5.7.0) → 5.9.2 - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 8.0, 8.1, 8.2, 8.3 ### 3rd party extensions - blackfire php probe (1.92.17) → 1.92.32 - [list of current releases](https://blackfire.io/docs/up-and-running/update) - blackfire agent/client (2.28.5) → 2.28.23 - [changelog](https://packages.blackfire.io/binaries/blackfire/2.28.23/CHANGELOG) - newrelic php probe and agent (10.21.0.11) → 11.7.0.21 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ## Another note on PHP 7.4 and PHP 8.0 EOL So far, we have been able to keep the unsupported versions PHP 7.4 and PHP 8.0 running well after their sell-by-date. There will be no updates, patches and security fixes from the PHP maintainers any more. Thus, these two PHP versions are provided from us at best effort. If a serious security issues comes to light, we will need to force update to the next PHP version with short notice. Please review your Apps with us, see what still runs on PHP 7.4 or PHP 8.0 and you are able upgrade. We know that it is painful and we feel you. We don't wan't to break your websites. We understand that there is often no time or budget to keep all projects updated. Yet, it is your duty as the maintaining developer to keep your software updated. ### Related - **[PHP version upgrade help article](https://help.fortrabbit.com/php-version-upgrade)** - [Supported PHP versions](https://www.php.net/supported-versions.php) - offical php.net website - [PHP 7.4 EOL announcement here](/php-74-eol) from October 2022 # PHP 8.5 Source: https://blog.fortrabbit.com/php-85-update Created: 2026-02-17 10:44:59 Author: Erin Strand Tags: changelog > PHP 8.5 is live on both platforms: selectable in the dashboard, default for new apps, and available through the latest setting. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## New platform - PHP 8.5 can be selected in the dashboard - PHP 8.5 is default for all newly created apps - "Latest version" means you are already running PHP 8.5! ![PHP version setting](/images/php-version-setting.png) The link below may take you to that setting. You may need to put in your environment ID. :BlockLink{title="PHP version setting in dashboard" path="/environments/{{app-env-id}}/php/php-version "} ## Old platform We currently don't have plans to bring PHP 8.5 to the old platform. Patch releases for existing versions are planned though. ## New PHP 8.5 features There are some nice improvements for the language: - [URI Extension](https://www.php.net/releases/8.5/en.php#new-uri-extension) - [Pipe operator](https://www.php.net/releases/8.5/en.php#pipe-operator) (most loved/hated) - [Improved cloning](https://www.php.net/releases/8.5/en.php#new-uri-extension) - [array_first() and last()](https://www.php.net/releases/8.5/en.php#new-uri-extension) Most clients will not use these features directly because a framework or CMS usually sits between PHP and their code. ## Update policies We roll out major PHP releases a few months after the official release. We do this because early dot releases often ship important fixes, and we also wait until all supported extensions are compatible. PHP patch releases on the other hand are pushed to the new platform weekly, along with any security patches for system libraries and other linux components. PHP extensions on the new platform are upgraded quarterly. Current platform gets PHP updates once per year. If you need the latest features, then we suggest you try out our new platform! [Sign up now](https://dash.fortrabbit.com/signup) --- - [Update policies](/legal/policies/update-policies) # PHP & JS? Source: https://blog.fortrabbit.com/php-and-js Created: 2024-06-24 Author: Frank Lämmer Tags: opinion > PHP and JavaScript have grown apart. What is missing between them in 2024, seen from a company that hosts one and serves the other. Maybe I am not the best to judge here. I am not even a real developer. My role is more product ownership and design. But I wonder about the relation of PHP and JavaScript for 2024 and beyond. For a PHP hosting provider, that's an important question. A decade ago, we at fortrabbit were excited by recent improvements in PHP and its ecosystem - specifically Composer. PHP evolved beyond a Pretty HomePage language for simple websites into something you can build web applications with. Symfony and Laravel are great frameworks for that. Yet, we are still hosting more PHP websites than web applications today. Most websites here are build with a CMS system. Although those come in different flavours ([Craft CMS](https://craftcms.com/), [Statamic](https://statamic.com/), [Kirby](https://getkirby.com/), WordPress …), they can all use PHP to calculate something on the server side and spit out some HTML to the browser. It's a simple concept and maybe that's why it is so powerful. It's not prefect, but it works surprisingly well (SEO included), when done right. Templating engines like Blade and Twig make it fun to create views. So from my point of view: LAMP stack still rocks! But than there is the JS part and the CSS styles, for which you will usually want to have some tooling to compress the authoring files into production code. I don't know anyone doing that with PHP today. So somehow, you need to integrate some JavaScript tooling like Vite into your workflow. I don't ‘feel' the connection here. There is Livewire and Interia.js, both projects aim to minimize the gap between the JS and the PHP world. We looked into those, but for our new platform we settled with a JavaScript setup for all frontend properties (see [blog post](https://blog.fortrabbit.com/our-new-frontend-stack)). It felt more natural to not mix the eco systems. There recently was some PHP vs JS discussion going on. Polarisation helps getting attention: - Theo: [Why Don't We Have A Laravel For JavaScript?](https://www.youtube.com/watch?v=yaodD79Q4iE) - TLDR; Because we don't want to be such a closed eco system. - Aaron Francis: [Laravel vs React](https://www.youtube.com/watch?v=gRtv-BVkwA4) - A primer on the technical foundations and options frontend / backend - TLDR; It's not ‘VS' it's ‘AND', bind them with Intertia or LiveWire - Also much longer: [Mostly technical podcast with Taylor Otwell](https://www.youtube.com/watch?v=NC6h1Oaz1rM) Let's have a look what Craft CMS is doing. Craft CMS is a classical LAMP stack CMS with Twig templating. But it also offers a headless mode. The backend is a PHP application running on a PHP hosting service like ours, serving the GraphQL API and the control panel to edit content. The frontend is usually a JAM stack based application consuming GraphQL to display dynamic content from the database. That's great. But it is also more complex than doing it the old fashioned way. You probably need to have two hosting setups, one for the backend CMS, one for the frontend. Not all Craft CMS plugins will work with JAM stack frontends. GraphQL is a powerful weapon, it's easy to crash the server with it. There are all kind of extra considerations. Exchanging with our customers in support about Craft CMS with GraphQL shows me all the challenges. It's not that easy. Statamic was a flat file CMS and turned into ~~jack of all trades~~ a super versatile tool: Beside direct static file output, it supports a database and a headless mode. I would like to see ‘PHP AND JS' as well. But I am not sure if the current answers are enough. It seems to me that the JS world is currently extending classical flat file Jamstack apps by more dynamic features (server side rendering to some extend). We have been discussing ideas to provide hosting for JavaScript based applications for almost a decade. So far we have been hesitant. Everything in JS world is changing so fast. Putting out a service means commitment for many years. For the new platform we will start by providing integrated tooling to run `npm` tasks during deployment for all kind of build processes. We are also exploring ideas to include a Node.js runtime available with the apps (early stages). Please don't hesitate to share your requirements and use cases with us. We are eager to learn. In the meantime let me reminiscence about the good old simple web and pretty home pages. I recently stumbled over [Textpattern](https://textpattern.com/) and [Moveable Type](https://movabletype.org/). It's great to see that both are still around. # PHP 5.6 & PHP 7.0 EOL FAQ Source: https://blog.fortrabbit.com/php-eol-faq Created: 2018-12-14 Author: Frank Lämmer Tags: webdev > What else you need to know about the upcoming EOL of the two PHP versions 5.6 and 7.0. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. This is part 4 of a series on the PHP upgrade path. See the other parts as well: 1. [On PHP deadlines](/on-php-deadlines) — PHPilosophical context … 2. [Testing PHP for version compatibility](/php-testing) — How you can test your code will still run. 3. [PHP 7.2 upgrade path](/php-upgrade-path) — Hands on instructions for our clients on how to update. 4. **PHP EOL FAQ** (this post here) — Anything else our clients need to know. ### How do I know if my Apps need to be updated? **Visit your Apps in the fortrabbit Dashboard, check the PHP settings.** When the version is lower than 7.1, you will need to update. You will also see a big warning in that case. In addition will also send direct mailings to all Owners of Apps still running on deprecated versions of PHP. This will include which individual Apps are affected. ### How do I update? ![php settings in the fortrabbit dashboard](/images/php-settings-in-the-dashboard.png) **Updating the PHP version on fortrabbit is easy.** Within the Dashboard, visit your App, click on the PHP Settings. Select a different version, click save. But you might also need to bring you code base in shape. ### How can I test if my App will work with a newer PHP version? We recommend to first update your local development installation. There you can easily test and debug. But if you prefer open-heart surgery, you can also just switch the version on your production App with fortrabbit, like described above. That will show you results quickly. You can still change back. ### How can I run automated tests? Glad you asked. Please see our [dedicated article for that](/php-testing). ### How likely is it that my App will not work? When your code base is not too old and when you have kept your software dependencies up-to-date, chances are very high that your code will just run. When your code base is older and your dependencies are outdated, chances are less high. There is no rule of thumb, each App is unique. ### What's the time-line for the switch? The official security support for the two PHP versions ends in December 2018, but that's where everybody is on holidays. So we plan to do the switch in **February 2019**. The final date will be announced, a few weeks before. We will consider your feedback on this. ### What will happen when I miss the deadline? All Apps on PHP 5.6 and PHP 7.0 will be upgraded by us on the day of the switch. That means that we will change the underlying PHP version on your behalf. We will not test or touch your code. In many cases, that will make no differences to the Apps, except that they will run a few milliseconds faster. But in other cases this will also break the Apps from running, maybe partly, maybe entirely. ### Do I have to update to PHP 7.2 now? We recommend to update to PHP 7.2 now. That gives you the longest support time frame currently available, until 2020. PHP 7.3 will be released soon. But **you can also only to upgrade to PHP 7.1 now**. For that the support time frame will likely be until EOY 2019. The benefit is that you have to deal with less changes for now. ### What about mcrypt? mcrypt was a replacement for the even older Unix crypt commands. It allowed developers to use a wide range of encryption functions, without drastic code changes. mcrypt was available as a PHP extension. It was deprecated but still available in PHP 7.1. For PHP 7.2 it was completely removed. The general recommendation is to use OpenSSL instead. Libsodum might be another alternative. mcrypt was quite popular and used by many libraries and systems. Craft CMS for examples relies on Yii, which itself relied on mcrypt for a long time. With Craft 2.7 Yii 1.1.20 is used also [mcrypt_compat](https://github.com/phpseclib/mcrypt_compat) an mcrypt polyfill was bundled. That makes Craft 2 compatible with PHP 7.2 - still consider Craft 3. So please make sure to have your framework or CMS updated at least to the latest available MINOR or PATCH version. For those who are dealing with that directly: Check out if you can implement an alternative solution. Otherwise first stick with PHP 7.1, which is still available now. ### Which PHP versions are supported on fortrabbit? fortrabbit is a managed PHP hosting platform. We maintain the PHP versions for you. You can select the PHP version for each App individually within the Dashboard under the PHP settings. You don't need to install or compile anything. Upgrading PHP on the server side is only a few clicks away here. New PHP versions on fortrabbit are added when all extensions are ready and we have performed some testing. As of this writing the current default version for new Apps is PHP 7.2. Here, PHP versions differ by MAJOR (PHP 5, PHP 7) and MINOR releases (PHP 7.1, PHP 7.2), as with semantic versioning. We leave upgrading to you, as far as we can. We try not to update MAJOR or MINOR releases of your existing Apps for as along as possible to make sure nothing will break. PATCH releases, like from PHP 7.2.**1** to PHP 7.2.**3** will be applied automatically. ### What are the current versions of popular software? Here are some popular PHP projects - at their current version as of this writing - and their required or at least recommended PHP versions: - **Laravel [5.7](https://laravel.com/docs/5.7/installation#server-requirements)**: PHP >= 7.1.3 - **Craft CMS [3.0.25](https://docs.craftcms.com/v3/requirements.html)**: PHP >= 7.0 - **WordPress [4.9.8](https://wordpress.org/about/requirements/)**: PHP >= 7.2 - **Symfony [4.1](https://symfony.com/doc/current/reference/requirements.html)**: PHP >= 7.1.3 - **Neos [4.0](https://neos.readthedocs.io/en/stable/GettingStarted/Installation.html#requirements)**: PHP >= 7.1 - **Drupal [8](https://www.drupal.org/docs/8/system-requirements)**: PHP >= 5.5.9 - **PHPUnit [7](https://phpunit.de/announcements/phpunit-7.html)**: PHP >= 7.1 ### But I am not a developer Please contact your developer regarding this. Remember: fortrabbit is a self-service hosting for sophisticated developers and their clients. ### Can you help me with the updates? Sure! We are here to help. As usual, prepare your question to include sufficient details and ask don't hesitate to ask us right away in our support chat. # PHP Hosting Possibilities Source: https://blog.fortrabbit.com/php-hosting-possibilities Created: 2015-05-05 Author: Frank Lämmer Tags: opinion > A stubborn look at hosting options for developers — shared, VPS, cloud and PaaS — and which of them fits which kind of project. 2026-03-19: This article is super old, values still hold up. Have a look at [FindHost](https://findhost.app/), our register of hosting providers, as well. ## Another self-opinionated hosting guide Trying to understand state-of-the-art hosting solutions. This article is for YOU, the developer — freelancer, small team, digital agency, startup. ## Prologue Let's face it: [web hosting is a market for lemons](http://www.welton.it/articles/webhosting_market_lemons.html). There are so many providers. New categories are emerging. Borders blur. Microservices everywhere. It's complex. It's noisy. It's hard. > The popular wisdom that cloud computing comes in three flavors — SaaS, IaaS and PaaS — no longer describes reality. We find that vendors are blurring the lines … — **John Rymer & James Staten** for Forrester Is hosting finally a commodity? Is it horsepower for bucks? What about value, productivity and developer happiness? We run a hosting service ourselves. So we are carefully studying how developers are choosing vendors. Naturally, we see a lot of "peer intelligence": What are the other kids using? And we also see confusion. Our service for example is very abstracted, so there are **[no servers](http://help.fortrabbit.com/the-platform#toc-architecture)** — still we get support tickets from people asking about their server with us. Let's clear some dust here. ## Old school hosting providers It's about hosting packages. They usually run data centers and bare metal servers themselves. You'll get all-in-one packages often including even domain and email services. Lot's of stuff for little money. Mostly for hobbyists, real developer tools are often missing. - [gandi.net](https://gandi.net) - [OVH](https://www.ovh.com) - [GoDaddy](https://godaddy.com/) - [Hetzner](https://www.hetzner.de/ot/) - [Media Temple](http://mediatemple.net/) - and many many many others ## New school virtual boxes It's about servers. Actually just a category of classical hosting, but somehow special. A popular choice among devs. Affordable, straight forward, total control and freedom of choice as the root user. With the flexibility comes responsibility for maintaining and securing your box — are you SysOp enough? Horizontal scaling is hard. But hey, it runs on SSDs! - [Linode](https://www.linode.com/) - [Digital Ocean](https://www.digitalocean.com/) - [ServerGrove](http://servergrove.com/vps) - and others ## Cloud enterprise players It's about services. The big guys are operating here. The clouds wholesale trade were you'll need a degree in rocket science to understand the product palette. But once into that, you only need to provision your cloud fleet. Cool for big teams, big projects, big budgets. - [Amazon Web Service](http://aws.amazon.com/) - [Microsoft Azure](http://azure.microsoft.com/) - [Google Cloud](https://cloud.google.com/) - and very few others ## All in one platforms It's about Apps. Apple-like: a black box, an end-to-end experience. High abstraction, no file-system, 12-factor instead. Streamlined so that everything hopefully fits together nicely. Limited in possibilities but managed and production-ready. We have automated DevOps so you don't have to. This space has a wide variety. Some vendors offer a very wide spectrum on solutions, others are specialized in certain programming languages or even applications / CMS systems. - [Heroku](https://www.heroku.com/) - [Engine Yard](https://www.engineyard.com/) - [Platform.sh](https://platform.sh/) - [Clever cloud](https://www.clever-cloud.com/) - [Viaduct](https://viaduct.io/) - [openshift](https://www.openshift.com/) - [cloudsigma](https://www.cloudsigma.com/) - [cloudControl](https://www.cloudcontrol.com/) - [Jelastic](https://jelastic.com/) - [elasticdot.io](https://elasticdot.io/) - [anynines](http://www.anynines.com/) - [pantheon](https://pantheon.io/) - [fortrabbit](http://www.fortrabbit.com) < hey, that's us - [many more at paasify.it](http://www.paasify.it/vendors) ## Extensions & glue Here comes the herd of one-trick ponies. Decouple all the things! Focus on one part and be really good at it. If this then that. Combine infrastructure resources with other services. ### Server provisioning & management Run your servers on any vendor and have web-based GUI to control them. The cPanel for the cloud. Filling the gap between raw computing resources and an easy-to-use developer interface. - [serverpilot](https://serverpilot.io) - [Laravel Forge](https://forge.laravel.com/) - [PuPHPet](https://puphpet.com/) < open source ### Containers ![VMception](/images/dawg-vmception.jpg) Docker is everywhere, at least on [HN](https://hn.algolia.com/?query=docker&sort=byPopularity&prefix&page=0&dateRange=all&type=story). The very successful "leftover" from an all-in-one platform. Now a huge ecosystem — a cross-platform cloud standard. Automating provisioning. Do you want to manage containers the rest of your life? Go ahead download it, it's open source. Docker as a Service providers are here: - [tutum](https://www.tutum.co/) - [StackDock](http://stackdock.com/) - [Joyent](https://www.joyent.com/) - [Fynn](http://flynn.io/) < kickstarter open source - [AWS ECS](http://aws.amazon.com/ecs/) > This (2015) will be the year that containers begin to be used heavily in production, as the missing pieces begin to appear. Docker itself, Mesosphere, and CoreOS, along with others are starting to provide the most key ingredient: orchestration. While this is important, we believe the bigger winners in this category will be those who abstract away containers entirely, so that app developers can focus on writing software instead of managing containers. — **James Lindenbaum**, [Heavybit](http://blog.heavybit.com/blog/jameslindenbaum-eoy) ### Deployment helpers Your code lives on GitHub or on Bitbucket. Now: how to move that over to the infrastructure? There is a service for that: - [ftploy](https://ftploy.com/) - [deployhq](https://www.deployhq.com/) - [dploy](http://dploy.io/) & [beanstalk](http://beanstalkapp.com/) - [envoyer](https://envoyer.io/) ## Epilogue The higher the abstraction grade, the less you need to care about OS level stuff — which doesn't mean that abstraction layers are for noobs. Ship code now instead of configuring your architecture first. But higher abstraction gives you less options — deploy only this way. Ever tried to run iOs on a Samsung? When combining raw infrastructure with third party services you risk some quirkinesses. Never trust a system you didn't forge yourself. Reinvent the wheel, master complex technologies, have more choice, pay less and be responsible for everything yourself. Good luck with that. You have many options. Choose something that fits your skills, business needs and preferences. ### Similar topics, same blog - **[Cloudscapes](/comparing-cloud-hosting-platforms)** a cloud hosting solutions compared - **[Cloudscapes revisited](/cloudscapes-revisited-php-cloud-overview)** a cloud hosting solutions overview - **[Understanding the fortrabbit platform](http://help.fortrabbit.com/the-platform#toc-architecture)** more on our platform - **[What the hosting and the meat market have in common](/what-the-hosting-and-the-meat-market-have-in-common)** some general ranting - **[Where to host my site now?](/where-to-host-my-website-now)** decision help for basic hosting needs # PHP renaissance collection Source: https://blog.fortrabbit.com/php-renaissance-collection Created: 2012-10-02 Author: Frank Lämmer Tags: opinion > A collection of links on the modern side of PHP, gathered when the language was shaking off its spaghetti-code reputation. > PHP development began in 1994 when the Danish/Greenlandic/Canadian programmer Rasmus Lerdorf initially created a set of Perl scripts he called "**P**ersonal** H**ome** P**age Tools" to maintain his personal homepage. - Wikipedia Since then a lot of spaghetti code has been written. PHP is the popular programming language everybody complains about. We see a new rise of sophisticated PHP programming. Here are some bits and pieces. ### Technologies * PHP5.4 - the latest version with new features * [Composer](http://getcomposer.org/) - Dependency Manager (See also [here](/handle-your-dependencies-with-php-composer)) * [PSR](https://github.com/pmjones/fig-standards) - PHP standards * [Modern](http://proemframework.org/) frameworks based on [decoupled](https://github.com/illuminate) components ### Tweets https://twitter.com/genexp/status/244534837598355456 https://twitter.com/nikita_ppv/statuses/215070429495304192 ### Further Readings * [PHP is much better than you think](http://fabien.potencier.org/article/64/php-is-much-better-than-you-think) by Fabien Potencier >[HN](http://news.ycombinator.com/item?id=4198271) * [PHP the right way](http://www.phptherightway.com/) the definite guide by Josh Lockhart >[HN](http://news.ycombinator.com/item?id=4212568) * [Is this the PHP renaissance?](http://articles.firstclown.us/post/is-this-the-php-renaissance) by Joseph Erickson * [PHP Ecosystem Update](http://philsturgeon.co.uk/blog/2012/07/php-ecosystem-update) "The Best Worst Language around" by Phil Sturgeon * [PHP 5.4 is here! What you must know](http://net.tutsplus.com/tutorials/php/php-5-4-is-here-what-you-must-know/) by Dejan Marjanovic on net.tuts * [Practical PHP 5.3](http://de.slideshare.net/nateabele/practical-php-53) slide from Nate Abele Missing something? Please comment! # Testing code for PHP 7 Source: https://blog.fortrabbit.com/php-testing Created: 2018-09-19 Author: Erin Strand Tags: webdev > Run automated compatibility checks against PHP 7.2 before switching a live app, and catch the breaking changes ahead of time. ## The PHP upgrade series This is part three of a series on the approaching end of life of PHP 5.6 and PHP 7.0: 1. [On PHP deadlines](/on-php-deadlines) - Background information and some trivia 2. [PHP upgrade path](/php-upgrade-path) - Minimum efforts upgrade 3. **[Testing for compatibility](/php-testing) - Run automated PHP7.2 checks < YOU ARE HERE** 4. [PHP EOL FAQ](/php-eol-faq) — Questions on the transition for fortrabbit clients ## Prerequisites This article is for sophisticated developers running PHP web applications, Laravel, Symfony or alike. The path provided is of general nature, so not only for fortrabbit clients, nothing in here is specific to our platform. ## Problem You are about to migrate to a current version of PHP, maybe to PHP 7.2, maybe from PHP 5.6, PHP 7.0 or PHP 7.1. You are doing this in your local development environment first and you have already upgraded your core dependencies. Now you want to find out if your own code might cause problems with a new PHP version, and also double check that all dependencies actually have full support. ## Reading Tips If you are curious about what has changed in between PHP versions, have a look at the very detailed PHP migration guides. Maybe you see a feature that you already know you are relying on in your code, and will have to change. - [Migrating from PHP 5.6.x to PHP 7.0.x](http://php.net/manual/en/migration70.php) - [Migrating from PHP 7.0.x to PHP 7.1.x](http://php.net/manual/en/migration71.php) - [Migrating from PHP 7.1.x to PHP 7.2.x](http://php.net/manual/en/migration72.php) But reading through all of those and matching manually to every single line of your code is quite the task, luckily we have automation! ## Automated code analysis Automated code compatibility testing helps to detect possible problems in your code. Install and run a tool locally to check your code before deploying it to your production application.

Code analysis tools

There are a quite few PHP code check tools you can run on your code to verify it is compatible with the latest PHP version: - **[PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility)** - PHP version compatibility analyser - **[rector](https://github.com/rectorphp/rector)** - Instant upgrades and instant refactoring of any PHP 5.3+ code _(added 2019-09)_ - [Phan](https://github.com/phan/phan) - Static analyzer and PHP 7 checker - ~~[PHPStan](https://github.com/phpstan/phpstan) - PHP Static Analysis Tool, check [Larastan](https://github.com/nunomaduro/larastan) for Laravel (no support for checking version compatibility)~~ - ~~[Exakat](https://www.exakat.io/) - Security, code smells, quality & bugs. OS + commercial (no support for checking version compatibility)~~ - ~~[PHP 7 CC](https://github.com/sstalle/php7cc) - PHP 7 Compatibility Checker (no longer supported)~~ - ~~[PHP 7 MAR](https://github.com/Alexia/php7mar) - PHP 7 Migration Assistant Report tool (probably outdated)~~ - [WordPress PHP Compatibility Checker](https://wordpress.org/plugins/php-compatibility-checker/) - a WordPress plugin - **PhpStorm IDE** users can also make use of a "PHP 7 Compatibility Inspection", which (now) can be found under "Language Level" in the settings. We have tested all of them briefly. They all work in rather different ways with different features and output. For the problem we are trying to solve in this article, we recommend **PHPCompatibility**. It gives you the most comprehensive help in finding deprecated features and syntax in your code. ### Running a PHPCompatibility check Using PHPCompatibility requires you to first install [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) globally and then configure PHPCompatibility as the code standard to use. We find that the easiest way to run it is with Docker, since that cleanly separates your local PHP setup from the tool. #### Using the fortrabbit Docker image of PHPCompatibility We have created a ready to use image called [phpco](https://github.com/fortrabbit/phpco-docker). You can easily spin it up by adding this bash function. First make sure you have [Docker](https://docs.docker.com/install) installed on your machine. Then execute this in your local terminal: ```shell phpco() { docker run --init -v $PWD:/mnt/src:cached --rm -u "$(id -u):$(id -g)" frbit/phpco:latest $@; return $?; } ``` Now you can directly use the tool in your current shell session. If you want you can also add this line to your `.bashrc` to have it available on startup of all new sessions. This example command will do a full check of all `.php` files in the current directory for PHP 7.2 compatibility. ``` phpco -p --colors --extensions=php --runtime-set testVersion 7.2 . ``` ![run php compatibility check](/images/php7-phpco.png) As it completes you will see a list of warnings and errors in your code. If you are getting a lot of warnings, but only want to deal with the stuff that will actually break, add `-n` to only show errors. [See docs for all `phpcs` command line flags here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage) **Heads up**: Since this is running within a docker container, the paths to your source files will start with `/mnt/src/` instead of the actual absolute path on your host computer. [Read more about our `phpco` container on GitHub](https://github.com/fortrabbit/phpco-docker) #### Dealing with dependencies that fail compatibility checks You will likely find errors also in your Composer dependencies. Of course you are not going to manually fix those. Here are some tips on how to deal with them. 1. Make sure the dependency is actually updated to the latest available version, [see our upgrade article on how to update](/php-upgrade-path#). 2. Check if you are actually using that specific part of the library, if not then then you can probably ignore the warning for now. 3. Test if the feature actually breaks when running the code, this compatibility check tool is only a best effort hint. 4. Contact the maintainer of that library and ask them to fix the problem. 5. Try to fix the problem yourself and send them a pull request :) To ignore these dependency problems for now and focus on only your code you can exclude the `vendor` folder with `--ignore`. Checking for PHP version 7.2 is the default so we can also remove that argument. ``` phpco -p --colors --extensions=php . -n --ignore="vendor/" ``` ## Further tests You are hopefully following test driven development patterns? Now is the time that all your automated tests come to great use. Your individual tests are probably one of the best ways to see if your application is working properly. Fire up PHPUnit and run test your tests again. Finally, manual testing can also catch a lot of problems that automated tests can never see. Click around your website and make sure all important actions works as expected ;) ## Closing words There is no easy way to carefully upgrade your PHP application to the latest version. An up-to-date mindset with incremental updates helps to keep your code fresh and clean. # PHP 7.2 upgrade path Source: https://blog.fortrabbit.com/php-upgrade-path Created: 2018-09-19 Author: Erin Strand Tags: webdev > Security support for PHP 5.6 and 7.0 ends in December 2019. The minimum-effort route to move an app to PHP 7.2 before then. For the current compatibility matrix and upgrade paths, see :ContentLink{href="/old-platform/php-version-support" text="PHP version support on fortrabbit" prefix="www"}. ## The PHP upgrade series This is part two of a series on the approaching end of life of PHP 5.6 and PHP 7.0: 1. [On PHP deadlines](/on-php-deadlines) - Background information and some trivia 2. **[PHP upgrade path](/php-upgrade-path) - Migration guide < YOU ARE HERE** 3. [Testing for compatibility](/php-testing) - Run automated PHP7.2 checks 4. [PHP EOL FAQ](/php-eol-faq) — Questions on the transition for fortrabbit clients ## Prerequisites When your code base is new, chances are very good that upgrading your PHP version will just work. When your code base is old, like older than 2 years, chances are less but still good. This guide will take you through all the steps needed to make sure your upgrade goes smoothly. ### Do you really have to update? We DO NOT recommend using outdated software, but we also understand real life scenarios. Sometimes it is difficult to find the time to upgrade an old project. Maybe you can come by with just a minor update without too much hassle? This is difficult to answer, projects rarely specify if their older releases support PHP 7.2 or at least 7.1, but here are some we know of: - **Laravel**: It seems that **5.1.11** has [support for PHP 7](https://stackoverflow.com/questions/34308160/is-laravel-5-1-compatible-with-php-7) - **Symfony**: Even **2.8.29** can run on PHP 7.2. Remarkable! - **Craft CMS**: Recently released **2.7** [supports PHP 7.2](https://craftcms.com/news/craft-2-7) with mcrypt polyfill - **WordPress**: We have tested version 4.4.16 which is the latest release from 4.4 which was published in 2015. Still we recommend to update. ## 1 - Update your local development environment We recommend to have a local development environment, also see our [help article on that](https://help.fortrabbit.com/local-development). So the first thing you need to do is make sure that your local PHP version is up-to-date. Depending on how your local development is set up, the path to upgrade is different. If you are running PHP directly on your computer, then a simple `php -v` prints out the PHP version. Beware, if you are using [MAMP](https://www.mamp.info/en/) or [XAMPP](https://www.apachefriends.org/index.html), this is not the version of PHP your code runs on. With these tools you have to use their GUI to select the PHP version you want. ![print your php version](/images/php-version.gif) To upgrade your local PHP on macOS, [Homebrew](https://brew.sh/) is a popular package manager you can use. Homebrew also controls the PHP version used by [Laravel Valet](https://github.com/laravel/valet). But if you are using [Valet+](https://github.com/weprovide/valet-plus) that tool has built in support for switching PHP versions (fancy!). **Beware:** If you want to use a one-click-update feature of a CMS like WordPress, CraftCMS or similar. You have to run that one-click-update locally BEFORE upgrading your local PHP, otherwise the admin GUI (wp-admin or control panel) might break. When you are running a more complex setup with PHP virtualized, such as Vagrant, Virtual Box or Docker, you have to dig in to your specific virtualization setup to see how to upgrade PHP. If you don't have a local development environment yet: Reconsider that now. A work around might be to use an additional App for that on fortrabbit. ## 2 - Update your software dependencies We recommend to get your dependencies up-to-date as well. Up-to-date software will run on an up-to-date PHP version. ### 2.1 - Updating with Composer Applications based on PHP frameworks like Laravel and Symfony are usually updated with Composer which keeps track of all dependencies. Issuing `composer outdated` in the Terminal will give you a list of outdated packages. Those in red need can easily be updated. Those in yellow also need to be updated but might cause trouble because they are major version upgrades. ![composer outdated](/images/composer-outdated.png) To update a dependency, simply change any required versions in your `composer.json` to a newer version and then issue a `composer update` to actually install the required updates. Keep in mind that the `composer outdated` command does not care about PHP versions. It will only tell you about available updates for your dependencies, but hopefully newer packages should support newer PHP versions as well. ### 2.2 - Updating a CMS Many Content Management Systems, like WordPress, Craft CMS and Grav come with a built in update feature. So you can simply login to the admin area of the CMS and hit a button to update. ![web interface update in CraftCMS](/images/web-interface-update.png) **Beware:** With fortrabbit, those changes only happen on the file system and are not reflected in Git. This is fine when you are using SFTP, otherwise read more in our [setup guide for WordPress](https://help.fortrabbit.com/install-wordpress-4-uni#toc-updating-wordpress) or [update guide for Craft CMS](https://help.fortrabbit.com/craft-3-tune#toc-updating-craft). **Tip:** WordPress also has a handy plugin to check whether your other plugins will work with the latest PHP version: [PHP Compatibility Checker](https://wordpress.org/plugins/php-compatibility-checker/). ## 3 - Test it When you have upgraded your local PHP version as well as your projects dependencies, it's time to make sure nothing is broken! Open your browser and try out as many views and actions as you can in your local development setup. If you are running a lot of custom code you have written yourself, we recommend that you run an automated code analysis. It checks your code and finds any deprecated functions that might break. [See our analysis article →](/php-testing#code-analysis) ## 4 - Go live with the updated version Now, as everything is up-to-date and tested in your **local** development environment, it's time to bring the updates to fortrabbit. ### 4.1 - Change the PHP version on fortrabbit Updating the PHP version for your fortrabbit App is as simple as pie: ![php settings in the fortrabbit dashboard](/images/php-settings-in-the-dashboard.png) 1. Visit your App in the fortrabbit Dashboard 2. Go to the PHP settings 3. Select PHP 7.2 or at least PHP 7.1 from the drop-down menu 4. Hit save Changes can take two minutes to be applied. You can also test-run this. When your App is not running under the newer version of PHP you can switch back to the deprecated version for another while and find out why first. ### 4.2 - Deploy changes Now, quickly after the new PHP version is in place, deploy your updated code from your local development to your fortrabbit App, either with [Git](https://help.fortrabbit.com/git-deployment) or simply by [SFTP](https://help.fortrabbit.com/sftp-uni) or by [rsync](https://help.fortrabbit.com/rsync). Don't forget that you might also have to run database migrations so that your database structure matches the latest code version. WordPress and Craft CMS automatically handle this in the web UI. For any other system, see their documentation on how to properly update the database. ## Cheers Thanks for taking the time to keep your software up-to-date. # PHP upgrade path (5.4), 5.6, 7.0 Source: https://blog.fortrabbit.com/php-upgrade-path-5-4-5-6-7-0 Created: 2015-06-23 Author: Oliver Stark Tags: changelog > Which PHP versions fortrabbit supports and for how long, from starting out on 5.4 in 2013 through the moves to 5.6 and 7.0. ## PHPast & PHPuture We've started our hosting platform with PHP 5.4 in 2013. That time most hosts ran on PHP version 5.2, 5.3 or even 4.x something. For us it was obvious to use the latest stable version of PHP. It was easy and not a big move, as we didn't had to support clients with legacy applications. Each release branch of PHP (5.4, 5.5, ...) is supported by the PHP core team for 3 years - two years fully, plus an additional year for critical security issues only. Most hosting companies don't care about these releases, they support old versions for forever and slowly adopt the latest. We think it's a good idea to stick to the PHP release cycle. ## Deprecating 5.4 The PHP 5.4 branch will reach it's [end of life](http://php.net/supported-versions.php) in Sept 2015 — that's less than 3 months ahead. We will also stop supporting this branch at the end of 2015 as no official security patches will be available after this date. We highly recommend to switch your existing Apps to PHP 5.6 NOW. There are only a [few backward incompatible changes](http://php.net/manual/en/appendices.php) which should not affect modern applications. To be on the safe side, you should test it with your test stage first. ## PHP 5.6 is the new default Some months a ago we've silently added support for PHP 5.6, the third version beside 5.4 and 5.5. Since PHP 5.5 will get security patches for only 11 more months, we've decided to make PHP 5.6 the new default for every new App created here at fortrabbit. Most PHP libraries and frameworks don't require 5.6 so far, but the chance is high this will change when they release the next major version. Sebastian Bergmann announced the minimum requirements for [PHPUnit 5.0](https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-4.7.0#phpunit-50) earlier this month and I hope others will follow this route. ## PHP 7 It's coming! You might have heard the news about the next major PHP release: a huge performance increase compared to PHP 5, but also language features like Scalar Type Hints, Return Type Declarations and the Null Coalesce Operator. However, as of this writing, there is no stable PHP 7 version out there - it's currently alpha. We can expect a final PHP 7 stable version at the earliest October 2015. In addition many extensions need to be [upgraded](http://gophp7.org/gophp7-ext/) to work with the new API. Since PHP 7 will be a major release it will introduce breaking changes in some way. The best way to test if your application works in PHP 7 is using [Rasmus' PHP7 dev box](https://github.com/rlerdorf/php7dev) — a vagrant box with multiple PHP versions. Lorna Mitchel shares in her latest [blog post](http://www.lornajane.net/posts/2015/php7-easiest-upgrade-yet) her experience porting a modern PHP 5 project to 7. TLDR: > Total lines of code change needed to make the @joindin API work on PHP7: zero # Platform updates, April 2026 Source: https://blog.fortrabbit.com/platform-updates-april-2026 Created: 2026-04-15 Author: Frank Lämmer Tags: changelog > April 2026 on the new platform: GitHub deployment comments, smoother dashboard flows, smarter deployments and better documentation. Beside many non-customer-facing-under-the-hood updates, we have shipped a number of smaller improvements for the new platform. Here is what's new. We are still trying to figure a consitent format for writing release updates, like this one. ## Dashboard ### GitHub deployment comments The fortrabbit GitHub app now comments on pull requests when code has been deployed. This makes it easier to see what is live without leaving GitHub. ::CallOut{alert} As part of this change, BETA testers who have the fortrabbit GitHub App installed received a mail asking you to confirm updated permissions for the GitHub integration. We still don't collect, share, or feed your data. We just write a comment on your PR. :: This is enabled by default, we may add a feature to disable it, based on user feedback. ### New payment method flow Adding a new payment method is now always a multi-step process. This makes the flow more reliable and easier to follow. Specifically for clients boarding. We also added more payment types recently. Beside others PayPal is avaiable. ### Domain splash screen After creating a domain, a new splash screen shows DNS instructions for both the WWW subdomain and apex domain on a single page. More domain updates to follow. ### Domain whois info There is now a new button to show whois data for a domain with the DNS table in the dashboar. It's based on RDAP, so it applies only to TLDs supporting that standard (excluding .de domains for example). This information can be helpful to debug DNS issues, like when the nameserver is actually elsewhere, or where the domain is hosted. We plan to extend that feature. ### Improved login and signup The login and signup flows now guide you more intelligently: - If you try to log in but we don't recognise your mail, you are redirected to signup. - If you try to sign up but we already know your mail, you are redirected to login. - If you try to log in with a mail address that is connected to GitHub auth, the GitHub login opens directly. We see some confusion from customers about the login where. They don't where they need to login. For now we don't have a better solution. ### Improved invite flows Inviting developers and clients is now smoother for the invited side: - No more double double-opt-in: clicking the invitation link also confirms the mail address. - After login or signup, you are forwarded directly to the confirm page and then through boarding. ## Docs ### Sitemap improvements The sitemap now includes last-updated timestamps for all pages. ### New article: test domains There is a new article covering test domains — how to use them and what to watch out for. ### New sections: AI integrations and code editors New doc sections cover AI tool integrations and code editors. We plan to update them, once deeper integrations wil become available. ### AI disclosure We now show a small disclaimer where AI was used in creating text. This is experimental for now. ## Fixed - Cancelled deployments now correctly show an end date. # Platform updates, August 2026 Source: https://blog.fortrabbit.com/platform-updates-august-2026 Created: 2026-08-27 Author: Frank Lämmer Tags: changelog > More temp space, log downloads that finish, a handful of dashboard fixes, and a website that lost its hosting guide. ## Platform and infra - **More temp space** - `/tmp` now holds 1 GiB. - **Log downloads stability** - Downloading a large log archive now more stable. ## Smaller improvements - **Jobs limit checked up front** — scaling the jobs component down below the number of jobs an app runs used to fail somewhere down the line. - **Environment variables keep their order** — the sort order set in the dashboard is saved and respected. - **Unsubscribe from retention mails** — the nudges for idle trials and apps have their own switch in the contact preferences now. - **Firewall rules de-dupes** — a custom rule for a port that is in the default list is rejected instead of quietly doing nothing. - **Remove a VATIN** — it could be added and changed, but not removed. Fixed. - **A new loading screen** — first paint respects dark mode instead of flashing white. ## Website and docs We retired the hosting guide on our homepage. It had grown into a comparison site living inside our marketing site, which is a strange place for it: nobody trusts a host to rank its competitors. It moved out to [findhost.app](https://findhost.app), a register of web hosts with no stake in the outcome — there is a [post about it](/findhost-a-register-of-web-hosts). Behind that, a stack of unglamorous fixes: search titles and meta descriptions, structured data for the pricing FAQ, smaller page payloads, and the plain Markdown mirror of every page. Half the links in our `llms.txt` pointed at files the build never wrote. ## Green hosting No real progress on the badge situation from last month. We carried the sustainability proof ourselves and got re-listed with the Green Web Foundation. The problem is that Green Web Foundation is not accepting AWS IPs to show as green energy, as long as AWS refuses to name them a contact. So projects hosted on fortrabbit no longer show as green with external checks (they usually depend on Green Web Foundation). On top of that we have to acknowledge that all hyperscalers now heavily invest in AI data centers powered by "natural gas", which makes me sad. ## Outlook - **Metrics** - Logs landed in July, metrics are the other half. We are working out what a first version in the dashboard looks like. Last big gap before general availability. - **Performance** - Still putting the new platform through load and scaling tests, still tuning. - **Agentic capabilities** - The reason this post is rather short, MCP, API and CLI will be released very soon. The new platform is still in BETA and we are working towards general availability. Everything above is tested, none of it is battle proven. If something breaks, tell us and we will get on it. # Platform updates, July 2026 Source: https://blog.fortrabbit.com/platform-updates-july-2026 Created: 2026-07-28 Author: Frank Lämmer Tags: changelog > A command palette for the dashboard, logs in the browser, MySQL timezone support, and a public API taking shape. Another month, another round toward general availability. We try to ship frontend features early and rough, then iterate on them as your feedback comes in. Most of the rest of our day to day work stays quiet: plumbing, cleanup, the boring parts that make the platform feel finished. As before, we keep the new and the old platform apart, since both still run side by side. ## Search from anywhere The actions menu we reworked last month grew up. It is now a proper command palette: hit `⌘K` (or `Ctrl-K`), start typing, and one box takes you anywhere. It searches across your apps, environments, teams, and people — and lists the actions you can run right there next to them. Find an app and jump to it, or trigger a task on it, without clicking through the navigation. :ContentClip{src="/images/filter-and-search.mp4" poster="/images/filter-and-search.png"} This is the shape we always wanted for the dashboard: less pointing and clicking, more typing what you mean. We will keep feeding more objects and actions into it. ## Logs in the browser ![Logs in the browser](/images/logs-poster.png) The big one. You can now read PHP, access, Apache, and Jobs logs straight in the dashboard — filter them, follow them live, download an archive. No SSH, no tailing files by hand. Nobody picks a web host for its log viewer. But observability is where the new platform was thin, and we wanted to close that gap before release. There is a whole post on it: [Logs now available in the browser](/logs-in-the-browser). Deploy logs got the same care. They now render ANSI colors, so the output reads like it does in your terminal, with clickable links where a tool prints them — plus a copy button to grab the whole log in one click. ## Platform and infra A batch of smaller infra work landed, mostly on the new platform. ### MySQL timezone support MySQL now ships with the timezone tables populated. Craft CMS lists this as a server requirement, and until now it was missing — so date and time handling that relies on named timezones works instead of throwing. ### Old platform: MySQL 8.4 The MySQL 8.4 migration on the old platform is finished. This month brought foreign key fixes and a `mysql-client` upgrade to match the server. ### Backup sizes The single-backup view already breaks down what a backup holds — files, database, general info. Now it also shows the sizes: the measured web and MySQL storage plus the compressed size of the archive itself. Not down to the byte, but close enough to know what you are about to restore. ### Coming soon - **More temp space** — `/tmp` is tight for some workloads. We are working on giving apps more room there. ## Docs and website - **Extended hosting guide** — the hosting overview now covers serverless PHP options alongside the classic setups, so the guide reflects the wider landscape and not just our own lane. - **Use cases** — the website now has a :ContentLink{href="/use-cases" text="use cases" prefix="www"} section, with related cases surfaced on the software and solutions pages, so it is easier to find the setup that matches what you are building. - **A more readable pricing specs page** — the :ContentLink{href="/pricing/details" text="pricing details" prefix="www"} page is now wired to the same specs we use everywhere, with a currency switch and a copy/AI button, and a machine-readable export underneath for the bots that read before they buy. - **Global docs review** — we read the docs end to end and fixed what drifted. - **Deep links that land** — anchor links on logged-in docs pages used to scroll to the wrong spot. Fixed. ## Smaller improvements - **Job limits, explained up front** — the new-job page now tells you when an app is at its plan's job limit, instead of letting the save fail. - **Environment names from your branch** — creating an environment now suggests a name based on the Git branch it deploys. - **Better stack detection** — new apps recognize Laravel 13, now the default in the picker, and detect Craft 6 as Craft rather than Laravel. ## From the blog We published a piece on the state of PHP application performance monitoring: [APM for PHP landscape in 2026](/apm-for-php). A take on what these tools do, where they help, and the meta-observability angle. ## Thanks to our clients We started collecting :ContentLink{href="/testimonials" text="testimonials" prefix="www"} on the website — real quotes from people running real apps with us, with links back to where they said it. Some of you have been with us for years and said kind things along the way. It means a lot, and it is nice to finally give those words a home. Thank you. ## About green hosting A heads-up for the environmentally minded. Many green-hosting checkers now show red for sites on fortrabbit — and for a big slice of the web along with us. Our electricity did not change. The dataset behind those badges did. The Green Web Foundation, which most of those checkers read from, archived AWS — our upstream — as a verified green provider, because it could not get anyone at AWS to keep the listing current. So anything running on AWS, us included, now comes back as "no evidence found". [They wrote it up here](https://www.thegreenwebfoundation.org/news/an-update-on-finding-representatives-for-large-hosting-providers/). As a downstream provider we can carry the proof ourselves — the upstream sustainability paperwork plus evidence that we run on that infrastructure — and get re-listed. We are on it. ## Outlook **Public API and a CLI.** The public API is no longer just a plan — it is being built, with real endpoints, filters, and its own docs. A command line tool to drive it is on the same track. Together they are the path to configuring apps from your terminal and your repository instead of only the dashboard. Early days, but moving. **Performance.** We are running the new platform through extensive performance testing — real CMS apps, synthetic concurrency, PHP scaling experiments — and tuning as we go. Some of it confirmed what we hoped, some of it sent us digging. This is ongoing work, and one of the last big things standing between here and general availability. A lot of what shipped this month — features and bug fixes alike — traces back to feedback. A few power users in particular keep sending sharp bug reports and pushing for changes; you know who you are, and it shapes the roadmap more than you might think. As always, feedback is welcome. # Platform updates, June 2026 Source: https://blog.fortrabbit.com/platform-updates-june-2026 Created: 2026-06-29 08:32:49 Author: Frank Lämmer Tags: changelog > US data center live, a new actions menu, social logins, and better mails. The new platform keeps moving toward general availability. This round has one headline feature plus a handful of refinements. As before, we keep the new and the old platform separate, since both run side by side for now. And we are still figuring a good changelog format. ## New platform ### US data center launched The new platform is now available in the US. North Virginia (`us-e1a`, AWS `us-east-1`) joins the European location, so you can choose where your app runs when you create it. This is also a milestone toward operating multiple data center locations worldwide — one of the reasons we rebuilt the platform in the first place. See the [US launch post](/us-data-center-new-platform) for the details on choosing a region, currencies, and a promo code for a free month. ### New actions menu We reworked the actions menu - the central place where you trigger operations on an app, environment, or other object. This is the main visual change this month. We will iterate over it and plan to make even more actions/tasks to become available. ![Action menu screenshot](/images/actions-menu-screenshot.png) See my [post about action oriented UX](/action-oriented-ux) for motivation. ### Social logins: Google and GitLab You can now sign up and log in with Google and GitLab, alongside the existing GitHub authentication. One less password to manage, and a faster path through boarding for people who already live in those accounts. ### Improved transactional and retention mails We went over the transactional mails — the ones we send around deployments, billing, invites, and account events — for clearer copy and more consistent formatting. The retention mails that nudge inactive trials and apps got the same treatment. ![Contact preferences screenshot](/images/contact-preferences-screenshot.png) Alongside that, there is a new contact preferences center where you decide which of these mails you want to receive. The essential ones (billing, security) always go out; everything else is yours to tune. ### Smaller improvements - **Pricing helpers and copy/paste** — the pricing views gained more inline helpers, and there is a nicer copy/paste interface for the numbers you actually need. - **Rate limiting surfaced in the dashboard** — SSH rate limiting is less verbose, and the current state is now visible in the dashboard instead of only showing up as terminal noise. We are still tuning the thresholds. - **Forms link to their objects** — every list item inside a form now links to the object's own page, so you can jump from a picker straight to the app, team, or payment method you are looking at. - **Better handling for symlinks during deployment** - Symlinks will get resolved when possible. ## Old platform ### MySQL 8.4 migration The MySQL 8.4 upgrade we announced in May is underway on the old platform. If you run a database there, check the [upgrade plan](/mysql-8-4-upgrade-plan) for the timeline and what to verify on your end. ## Outlook A lot of the work right now is quieter grunt work toward the final release, so the next big features are still a couple of months out. Two of them are worth a preview: **Observability.** We started building hosting metrics directly into the dashboard — like the old platform had, but much improved. This is tightly coupled with logs, which we want to pipe straight to the browser as well. Together they will make the platform feel a lot more complete. **Public API and infrastructure as code.** Our public API is in early stages. Related to it, we are revisiting a `fortrabbit.json` (or `.yml`, or maybe both) project file, so app configuration can live in your repository instead of only in the dashboard. As always, feedback is welcome. # Platform updates, May 2026 Source: https://blog.fortrabbit.com/platform-updates-may-2026 Created: 2026-05-22 09:01:59 Author: Frank Lämmer Tags: changelog > Longer trials, agent skills, environment thumbnails, and a MySQL upgrade on the way. We are still iterating on the format for these monthly updates. The split between the new and the old platform stays for now, as both are running side by side for the time being. ## New platform ### Trial extended from 72 hours to one week Every new app on the new platform now starts with a one-week trial instead of 72 hours. That is a meaningful change: each new app is a trial app, so a longer window means more room to actually try things. Connect a domain, deploy a real project, evaluate the platform without rushing. In later stages the same feature can be used for idea validation, weekend hacks, and free hosting until the stakeholder will take over billing. ### Agent skills We published a first preview of fortrabbit agent skills — the plain-text instruction files that teach AI coding assistants like Claude how to deploy code, sync databases, and run common platform tasks. See the [agent skills release post](/introducing-agent-skills) for the background. ### Website screenshots for environments Each environment now shows a thumbnail preview of its main domain. You see it in the environment list and on the environment overview page, so you can tell at a glance whether the site is live, broken, or showing the default placeholder. Useful when you have many apps or environments to keep track of. ### Re-deploy the same commit You can now deploy the same git commit again without changing anything. This helps when you need to retrigger a build after fixing an environment variable, swapping a service, or recovering from a failed deployment — no more empty commits. ### PHP runtime updates `imagick` now runs at 3.8.1 across every PHP version (8.1 through 8.4 were still pinned to 3.7.0), and Blackfire switched to calendar versioning. New platform will receive more frequent minor version updates, we are still figuring out the right format to publish this. **Tooling** - Composer: 2.9.4 → 2.9.7 - ImageMagick: 7.1.2-13 → 7.1.2-21 - MS ODBC for SQL Server: 18.6.1.1 → 18.6.2.1 **PHP extensions** - imagick: 3.8.1 — now consistent across all PHP versions - mongodb: 2.1.4 → 2.3.1 - ssh2: 1.4.1 → 1.5.0 - xdebug: 3.5.0 → 3.5.1 **Profiling and monitoring** - Blackfire PHP probe: 1.92.59 → 2026.4.1 - Blackfire CLI: 2.30.1 → 2026.4.2 - New Relic PHP agent: 12.4.0.29 → 12.6.0.34 ### Less verbose SSH rate limiting SSH rate limit messages are now less noisy. We are still tuning the thresholds based on real usage, so expect more adjustments here. ### Smaller fixes Many smaller fixes and improvements across the dashboard and platform. Nothing dramatic on its own, but the rough edges keep getting smoother. ## Old platform ### MySQL 8.4 upgrade upcoming We are preparing to upgrade MySQL on the old platform to 8.4. A separate post with the details, timeline, and what to check on your end will follow. ### Website screenshots fixed The website screenshot feature on the old platform is now working again. ### Statustool cleanup and migration After years on SorryApp, we have moved the old platform's status subscribers over to Better Stack — the same service the new platform already uses. Not an easy call, we liked SorryApp. But we prefer to keep the number of services we run small. Old and new platform still have separate status pages, and subscriptions stay separate too (we think that is fine): - [status.fortrabbit.com](https://status.fortrabbit.com) — old platform, for as long as it runs - [fortrabbit.betteruptime.com](https://fortrabbit.betteruptime.com) — new platform Better Stack only supports email subscriptions, so the Slack and Teams exports are gone. The fortrabbit Twitter status bot will also go silent. We also cleaned up the old subscribers list and removed everyone without an active account. Some people who subscribed with a different email may have been caught in that, but after more than a decade in business a thorough cleanup was overdue. We also fixed a data inconsistency where some subscribers had no region assigned. Region subscriptions are now mapped to app location. ## Outlook Planned for the new platform next: - **Logs and metrics** — proper observability is one of the larger gaps right now. - **US data center** — launch is getting closer. More on that soon. - **API and CLI** — bringing programmatic access back for the new platform. As always, feedback is welcome. # Post mortem September maintenance Source: https://blog.fortrabbit.com/post-mortem-september-2023-maintenance Created: 2023-10-04 10:14:11 Author: Frank Lämmer Tags: chronicles > A post mortem of the September 2023 internal maintenance: what went wrong across the nights in the EU, and what the aftermath was. * See the [introduction blog post](/september-2023-updates) for minor version changes * See the [main event on status page](https://status.fortrabbit.com/notices/oo2uy672ylbggpa6-internal-updates-maintenance-eu) for events The maintenance in the EU took place over a series of nights and was referred to as an 'internal update'. This type of update primarily involves non-client facing changes to the software. Keeping software updated is of course required to maintain security and stability. The main maintenance period began on September 1st and lasted until the 21st. We had to extend the maintenance window twice. The subject was to update the underlying Linux Operating System. We use Ubuntu, and both the host systems and container systems were updated. We generally use LTS versions, and such updates are performed every few years. The last time we performed this kind of update was in 2019, and [it was also challenging](/post-mortem-under-the-hood-2019-06). ## Related incidents Unplanned additional service regression happened - directly related to the maintenance. Client facing issues, we have posted: * 9th of Sep - [Certificate errors](https://status.fortrabbit.com/notices/gulify7kqvszys1z-tls-issues-for-some-apps-in-eu) * 13th of Sep - [Web delivery and deployment issues](https://status.fortrabbit.com/notices/hiohmhlw6tjr0qcm-ssh-sftp-connectivity-and-web-delivery-issues-for-some-apps-in-eu) * 17th of Sep - [Memcache related issues for Pro Apps](https://status.fortrabbit.com/notices/unhzkgi282ce0zvd-issues-for-pro-apps-in-eu-likely-related-to-memcache) * 24th of Sep - [Redirect issues](https://status.fortrabbit.com/notices/6uxf84ptyun5bh0e-redirect-issues-for-naked-domains-in-eu) * 24th of Sep - [Web delivery issues for Pro Apps](https://status.fortrabbit.com/notices/aqsx29b4ixiof45i-web-delivery-issues-for-some-pro-apps-in-eu) Most of the issues where only affecting a smaller number of Apps and specific services. Never the less, some clients faced multiple issues in short sequence. Ouch. ## Known issues A couple of smaller regressions became visible after the update. ### GeoIp database missing The GeoIP (GeoLite2) database was previously included. That's a service provided by MaxMind. The database and the extension are now been superseded by the GeoIP2 API, also by MaxMind. We forgot the database part, we have also not been aware that it is still in use. We have hot-patched Nodes for (2) clients requesting that file to be present. But it will not be available for all Apps. We are likely going to include it again with a future update to make it fully persistent. ### Ghostscript missing The Ghostscript library was initially missing. It can be used in combination with ImageMagick to tinker with PDF files, specifically creating preview images for PDF files. It was removed intentionally to avoid possible incompatibility issues with more recent versions of PHP. We currently provide PHP runtimes from PHP 7.4 to 8.2. We have hot-patched all Nodes so the extension is available now (and no issues so far). Again, we need to include it with the future rollout to make it fully persistent. ### Routing issues The before mentioned routing issues surprised us. Routing Nodes are sending traffic to the Apps. Those have also been upgraded of course. There is a daemon watching the distribution of Apps on routing Nodes. Somehow the routing Nodes ended up not correctly tagged, so the Apps have been redistributed in unexpected ways. We are still investigating the issue, at the time of this writing. ### Redeploy issues Although we tried to avoid this, the so called redeploy issue happened. This is a platform 'feature': When moving Universal Apps to different Nodes, a Git deployment get's triggered. This is usually welcome, but some of our clients neglected Git deployment in favor of SFTP or working on the App directly. In such cases old files from the old Git repo are going to replace files that are actually newer creating a bad version mismatch. More with our [help](https://help.fortrabbit.com/app#toc-version-mismatch-without-any-changes-made). We have been able to identify most if not all problematic Apps and hot patch them from snapshots. If your App has some old files now, that's maybe why. ### Some metrics are missing We are looking into missing FPM related metrics currently. Now fixed, you may see a gap in the metrics with our Dashboard. ## Reflections The entire project was prepared for over half a year, with extensive testing conducted in our staging environment. It was a significant undertaking that we took very seriously. However, as they say, "there is no test like production". The fortrabbit hosting platform is becoming old. Certain parts of the software are over 10 years old. We have a comprehensive knowledge base and a culture of knowledge sharing. Never the less, there is a lot of tacit knowledge that has to be relearned with such an update. We have now better documented the new processes and implemented new routines to improve stability. Currently, we spend most productive time developing a completely new version of the platform. The decision to either rewrite the entire system or iterate on it sparked controversy. Only time will tell if we are on the right path. The substantial amount of (old but functional) custom code and the complexity involved were strong arguments in favor of a significant change. It will take a while longer before we can showcase the new platform. It will incorporate the lessons we have learned from being a hosting provider for quite some time, including this experience. ## Thanks For your attention and to our understanding clients. # Post mortem for `Under the hood updates` Source: https://blog.fortrabbit.com/post-mortem-under-the-hood-2019-06 Created: 2019-06-28 Author: Frank Lämmer Tags: chronicles > A post mortem of the 2019 under-the-hood update: a global operating system upgrade that did not go as planned, and why. ## Project internals **Long time in preparation**: This was an internal update with focus on stability, security and agility, also a major internal mile stone and groundwork for future releases. It's biggest part was a global Operating System update. This alone - as you can imagine - brings lot's of changes. With it a lot libraries and dependencies have been updated, check our [original announcement](/under-the-hood-updates-2019-06) which only includes front-facing changes. It was a big and complex project and we have started working on it over a year ago. **End sprint**: We postponed the rollout multiple times. But then we forced ourselves — also due to external circumstances — to set a deadline. The whole team participated to make it happen. Already on home stretch, around a month before roll-out, we were still dealing with road blockers. That gave us less time for testing. We still decided to do it, as we became more and more confident that it was doable. **Roll out**: The actual implementation was planned to happen in two long sessions per data center region and some additional service level operations. The process took much longer than anticipated and spawned over weeks with multiple maintenance windows. ## Upgrade aftermath While in general, the platform was up and running, lot's of different smaller and bigger issues popped up. Those issues affected a smaller number of clients in US and EU running Universal and Professional Apps. ### General performance degradation We had big trouble identifying and hunting down general random performance issues. PHPeople reported slowness and sometime also time outs. Those started popping up around two days after the upgrades, sometimes affecting full Nodes, but sometimes only on certain Apps. We investigated in all kind of different directions, first trying to find if there is a pattern or if those are isolated individual cases. We saw it happening much more on the older PHP 7.1 version and with older software versions such as Craft 2 and Laravel 5.2. A first mitigation was to redistribute the Apps to new Nodes. But more support tickets came in, now on Pro Apps as well and it became clear that this is a more general issue. Still the number of support requests wasn't sky rocking. Additionally these issues were not very visible in our monitoring tools, as services still returned 200 OK. After days of intensive research we finally had a promising lead: There is a fortrabbit service called Drone. It manages the orchestration of all containers. We found it to slowly eat more and more memory. That of course will at some point make the system slower and use swap. We have then implemented a mitigation fix, restarting the Drone service in intervals, first on certain Nodes for monitoring and then globally by Monday this week (2019-06-24) everywhere. We are now testing different new builds of that service in our staging environment and will roll the "real fix" out as soon as we are confident about it. ### Re-deploy on Universal Apps Along the process of mitigating the performance issues, some Nodes had to be restarted affecting only a small number of clients. There is a "feature" to trigger a Git re-deploy, so all contents from Git will be re-synced into the App to make sure it's up-to-date. We know that this causes problems for some clients who have started using Git but later switched to SFTP or web updates. ### Metric issues There are different issues with metric aggregation. MySQL storage should now be displayed correctly. Fixes for performance (PHP requests) and web storage metrics are still outstanding and will come back soon. ### NewRelic issues Our current NewRelic implementation fails to send data. The issue is found and fixed. We manually applied a patch for a small number of clients. Global roll-out of the NewRelic fix will happen soon without any expected downtime or maintenance window. ### Possible new ImageMagick issues We are currently also investigating if the situation on image transforms has changed with this update. Re-cap: We have upgraded imageMagick back in February and [applied policy fixes](/imagemagick-issues). Please let us know if you have new issues there. ## Conclusions We have learned a lot with this update. Did we do something wrong? Well … Yes, we might have discovered one or another issue — like NewRelic not sending data — upfront in more proper testing. But the performance issues and other things are really hard to discover in testing. ## Some outlook The next two big topics we are having in pipeline now are: "**MySQL 8**" and "**HTTP/2**". With this upgrade we came closer to both. ## A big thank to our wonderful clients We are totally amazed how knowing and calm our clients have been in that situation - even at peak times when we were not able to reply in support as quickly as usual. Sorry for the inconvenience one more time and thanks so much for your understanding! Please ping us in support when you still have any issues ongoing. Make sure to give us sufficient details on the situation, provide as much info as you can. # Privacy Shield considered obsolete, possible impacts on our hosting platform Source: https://blog.fortrabbit.com/privacy-shield-obsolete-our-thoughts Created: 2020-09-15 Author: Frank Lämmer Tags: opinion > The European Court of Justice invalidated the EU-US Privacy Shield. What that means for a hosting platform and for its clients. TLDR; Keep calm and continue business. _DISCLAIMER: I am not a lawyer. This is not legal advice. I might be completely off the tracks. OPINIONs are kinda like my own but relate to the work I am doing at fortrabbit._ ## About the Privacy Shield The EU-US Privacy Shield is/was an international agreement to enable protection of personal data getting transferred over the Atlantic. It was designed as a follow up to the Safe Harbour agreement (which was considered obsolete before). EU citizens in Europe are protected by the General Data Protection Regulation (GDPR). The aim of Privacy Shield was to extend that abroad. _OPINION: As a citizen I like GDPR. As business owners we struggle to fully comply with it, it's complicated and bureaucratic. See our [GDPR ready post](/fortrabbit-is-gdpr-ready) from 2018. As a citizen I applaud [Max Schrems](https://twitter.com/maxschrems) for his success in court. As a business owner I fear the uncertainty this creates._ ## Does it matter for your favorite cloud hosting? "fortrabbit GmbH" is a company registered in Berlin, Germany, Europe. Our business is international. We use Amazon Web Services (AWS) as our infrastructure provider, as well as some other services, many from the US. The new privacy rules might have an impact on our clients in the following ways: ### Data we store on our clients The AWS data centers we currently use are in Ireland and the United States. We store our customer data (your Account information, like name, email and billing address) only in the Ireland region. We use a lot of other external services to run fortrabit. An up-to-date list can be found at our [sub processors list](https://www.fortrabbit.com/sub-processors). Some client data might be shared with those additional 3rd party services — think of customer support for example. We have received statements from all of our partners that they will continue "to uphold a strong protection of personal data, regardless the legal situation". See this [statement](https://postmarkapp.com/blog/postmarks-response-to-the-schrems-ii-judgment-privacy-shield-invalidation) by our sub processor Postmark, it contains a lot of details and background knowledge on the topic. In this regard, please also note our standard [privacy policy](https://www.fortrabbit.com/privacy) which is mirroring current GDPR practices. ### Data our clients generate Our clients are building websites on top of our services. These web applications and websites might also collect and store personal data. Technically we have access to that data, we have a [data processing agreement](https://www.fortrabbit.com/data-processing) (DPA) for that in place. It extends our terms and applies to all client relations by default. There are additional DPAs with each of our sub processors, especially with AWS. Depending on the AWS region hosted (US / EU), different privacy rules might still apply. Most of our clients are building classic websites, where most contents are fully public over the internet. _OPINION: If you have found the secret formula on how to turn lead into gold, maybe don't host it on our servers. For common websites and almost all web applications we are hosting, privacy might not be the number one concern._ ### Generated data There are also log files and other data, that might be considered personal information - is an IP address personal data? These log files are stored for some time on our servers. They are generated whenever someone from within the world wide web accesses a website or web application owned by one of our clients (or by us, like the blog you are on right now). ## Conclusions Mind that the fortrabbit cloud platform is an offering for professional PHP developers. We are constantly questioning all of our practices in that regard. We store as little personal data as possible by default, most of it is accounting related. We take privacy seriously. _OPINION: I don't think that this will play a big role in our B2B relations here. As far as I understand it, the new rules are interesting in regard to how big tech players collect personal data from their users. Namely, how will Facebook and Google continue to do business in Europe?_ # Release early, release often Source: https://blog.fortrabbit.com/release-early-release-often Created: 2012-10-05 Author: Oliver Stark Tags: opinion > Going generally available without a public beta period: the case for launching a hosting service early and iterating in the open. **Ready or Not - here i come?** Can we really go live that early? Shouldn't we do a public BETA period to gain more feedback first? __ _We think: YES we can!_ You can read it in any startup advice book: Launch early. Our new cloud hosting service is general available since yesterday. We build it within a fairly short time (~12 months) and had only a short closed BETA period (~1 month). We do managed hosting for over 5 years - a business where reliability is one of the core values. And Platform as a Service is just a label for a modern approach of scalable hassle-free hosting solutions. This PaaS market is very young and still a changing category in the wide field of cloud hosting. [Listening](http://philsturgeon.co.uk/blog/2012/10/cloud-hosting-php-pipe-dream) to customers and their needs will influence the way current services work. ### Is our platform really mature or yet another MVP or even just a tech demo? We hope that you take the time and check it out yourself. Our full featured freemium plan comes handy here. Please consider: * **It's built on top of AWS**. We are standing on shoulders of giants. We don't have to take care of all the bare metal. * **Our design is paranoid.** Relying on AWS is not enough. Nearly all components are redundant and in different availability zones. * **The underlying core software is proven to be stable.** De facto standard hosting components: Debian, Apache, Puppet, grsecurity & HAproxy * **We are experienced.** Our first generation hosting, a dedicated stack of own hardware, is still running. Uptime: 99.9% We are a a [small agile team](http://fortrabbit.com/about). Instead of trying to build an "[egg-laying wool-milk-sow](https://www.google.com/search?q=egg-laying+wool-milk-sow&hl=en&prmd=imvns&source=lnms&tbm=isch)" we focused on a optimized PHP stack. **It's just LAMP with deployment candy on top, but we like it.** The most important features, the ones you will need in production, are included - with attention to detail. The [documentation](http://support.fortrabbit.com/) is very complete. Our unique r/w-storage solution allows all type of work-flows. Billing works, you can pay with credit card and will get a nice PDF invoice each month. We tested everything intensively and integrated feedback from our BETA testers (thanks again!). From our perspective we've released a very solid 1.0 stable. But it's software and it cuts both ways: Things go wrong sometimes but they are easy to fix. We are looking forward to get more great [feedback](https://docs.google.com/spreadsheet/viewform?formkey=dE1LVHowMTVXM1pVX2FLZFpxNXlpdUE6MQ) (criticism & props) to move on the next release. # Remote SSH execution is here Source: https://blog.fortrabbit.com/remote-ssh-execution-released Created: 2016-06-01 Author: Frank Lämmer Tags: changelog, chronicles > Remote SSH execution runs artisan and other framework commands directly on the environment, without a tunnel and a special config. ## Until now To use `artisan migrate` and akin you needed to write a special tunnel config, then open up a tunnel via SSH to your database and then execute those commands locally — using both the tunnel and your special config file. Far from beautiful — we know. It also caused lots of support on our end due to lots of confusion on your end. ## From now on Execute SSH commands directly in your App! This allows you to run `artisan migrate` and variations without the need to open up a tunnel first: ``` ssh your-app@deploy.eu2.frbit.com php artisan migrate ``` That's of course not all. You can also use tinker-style commands to work directly on your App, utilize task runner such as [Envoy](https://laravel.com/docs/5.0/envoy) to automate reoccurring errands or simply list and check out all your deployed files. ## What do I need to change? Nothing, the old tunnel-way will still work as there are still valid use-cases (eg dump or import your database). Anyhow: now you can migrate with a little more style. ## Can I deploy using SSH/SFTP now? Sorry. This is still not possible, due to the New App infrastructure design: fast, advanced, secure and horizontally scalable. An essential part to make all that possible is the [ephemeral storage](https://help.fortrabbit.com/quirks#toc-ephemeral-storage) New Apps come with. So any changes to the file system you make with your remotely executed commands will be lost on a new deploy. ## Show me how to use it! * [SSH remote execution help article](https://help.fortrabbit.com/remote-ssh-execution) * [Laravel migrate and other database commands](https://help.fortrabbit.com/install-laravel-5#toc-migrate-amp-other-database-commands) * [Symfony migrate and other database commands](https://help.fortrabbit.com/install-symfony-2#toc-migrate-amp-other-database-commands) * [October setup database](https://help.fortrabbit.com/install-october-cms#toc-setup-database) * [ezPlatform initialize remote database](https://help.fortrabbit.com/install-ez-platform#toc-initialize-remote-database) # Roadmap to Hack App Source: https://blog.fortrabbit.com/roadmap-to-hack-app Created: 2015-04-20 Author: Frank Lämmer Tags: chronicles > The fortrabbit roadmap after the dashboard relaunch, and the groundwork already laid for the updates that follow it. ## The rough road ahead Just recently we have [relaunched our Dashboard](/the-new-dashboard-is-here). While primarily an optimization milestone, it already includes some groundwork for the upcoming updates. This is the about the rocky road that sometimes isn't visible because of all the stones. This is our roadmap to our next generation of Apps. ## A look back We [first started](/take-off-fortrabbit-php-platform-launched) our platform about two years ago. Back then we proud ourselves to bring best of both worlds together: a state-of-the-art cloud hosting architecture — with legacy support. We saw that this was a "missing link": While a renaissance of PHP — embracing modern practices — was already on the rise, the majority of PHP websites and applications was still build upon frameworks requiring classical setups. A legacy work-flow doesn't include Composer/Git and is based on SFTP (or SSH) to upload files. ### Persistent storage So we now have a unique cloud hosting solution with write-able storage. For the user it feels like the local storage of the server, while in fact a network image is mounted. This distributed storage system is solid and offers convenient ways to work. We engineered the hell out of it to make this stable on production grade level. ### Implications `+` A plus point is that the attached local storage can also be used for storing runtime data, logs, temp files and user uploads. `-` The storage might affect performance negatively. Apps making use of disk operations heavily are running a few milliseconds slower. While most of those issues can be solved with proper caching, this includes extra efforts for our clients. `-` Reliability is OK, but we want more. The network storage is fully redundant. There are fail-over mechanisms in place — the slave takes over when the master fails. However, we have experienced network effects, causing us to interfere manually more than we would like to. `-` The storage is pricey and we have to pass those costs to the clients. That's an issue as cheap VPS prices are anchored in the heads. Clients expect PHP hosting to be inexpensive. ### The PHP point of view WordPress helped to popularize PHP, cool. But i believe that it's traditional architecture prevents the majority of the PHP scene to move forward in terms of deployment, code organization and hosting. Just imagine what would happen, if the next WordPress release would finally include a native way to deploy with Composer and Git. Best practices would become common standard then. > When you have a hammer everything looks like a nail. PHP — a full-stack language — is used in all kind of scenarios. Our typical client has three Apps: one for the backend of his SaaS service, one for marketing website and one for the blog. All this is PHP. We should support all this to be the one-PHP-go-to-provider — delivering an end-to-end solution. ### The hosting point of view > Hosting is changing, bounders blur. The concept of the twelve-factor App is known for a while now. It's a collection of best practices for developing applications that can easily and effectively be hosted in cloud environments, without the need of persistent storage. Most traditional cloud hosting platforms expect you (their clients) to deliver 12-factor Apps. The bottom line is that you might have to adjust/enhance your coding and deployment practices. It's a bit more complicated, but more advanced. But then there is also Docker which somehow violates 12-factor principles and makes server orchestration in the cloud really simple. Something completely different. ### The Laravel point of view > Laravel is Rails for PHP. Laravel is by far the most popular PHP framework now. We love it and fortrabbit was built with that in mind. The majority of projects hosted on fortrabbit are built using Laravel. Laravel-creator Taylor Otwell himself however decided to offer commercial services around Laravel-hosting himself. Those solutions differ from our approach and are tightly connected to the framework itself. So it's hard for us to stay 110% compatible with all aspects of Laravel. ## A look ahead We have always been fans of the decoupled 12-factor-App design — it can really fly. And we believe that it makes sense to push that now. Docker is nice, but an higher abstracted service is even better for most of our clients. It's tempting to adjust our service to match the latest Laravel changes, but it's better for us to be more open. Our next generation of Apps will become BETA later this year. It's working title is still Hack App — and that's what it is going to be. # Craft CMS SEOmatic exploit info Source: https://blog.fortrabbit.com/seomatic-exploit Created: 2020-07-07 Author: Frank Lämmer Tags: chronicles > A critical vulnerability in the Craft CMS plugin SEOmatic. How to check whether an installation was affected, and how to clean up. Last updated: 2020-07-15 ## About the exploit The Craft CMS plugin SEOmatic by Andrew Welch helps web developers and website owners to implement modern SEO best practices — see the [plugin website](https://nystudio107.com/plugins/seomatic) and the [plugin on the Craft CMS store](https://plugins.craftcms.com/seomatic). The plugin is commercial ($99) and popular among the Craft community. In April 2020 a security issue for the version 3.2.46 of the plugin [was posted GitHub](https://github.com/nystudio107/craft-seomatic/issues/614) and fixed a day later with version 3.3.0 for the plugin. But a regression was introduced later on, so the issue remained for another while. The issue got the Common Vulnerability Exposure ID [CVE-2020-12790](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9757). It uses Server Side Template Injection (SSTI). So in other words, any code can easily be executed on your website. Here is a demonstration of exploiting the vulnerability: ## Identify if your installation is vulnerable Here is how you can check if your Craft CMS website might be affected: **1. Browser check** ``` https://domain.com/actions/seomatic/meta-container/meta-link-container/?uri={{4*4}} ``` Call the above URL. Replace `domain.com` with your own domain. Your website is affected if you get a json response that contains `meta-link-container?uri=16`. **2. Version check** You should also check for the installed version of the plugin. You can do so in the Craft CMS control panel under Utilities > System Report. Or you can check your `composer.json` file for the installed version as well. ## Check if your installation was actually hacked In case your Craft CMS installation is affected by the issue, hackers might or might not have made use of it. See if your App has been compromised like so: 1. Login to your App by SSH or SFTP 2. Review `htdocs/web` folder for suspicious `php` files - `index.php` is expected, other files usually not. 3. Compare the `htdocs/web/index.php` with your local copy of `index.php` We saw some hacked Craft CMS installations to be used for crypto currency mining. If in doubt, go ahead and contact your hosting provider (us). ``` # Some example files # file names are completely arbitrary %20mo.php %20tempek.php ad-center.php aindex.php ajax-index.php class-wp-style.php configindex.php mo.php peler.php siteindex.php tempek.php wp-admin/.htaccess wp-admin/d3d3LmR1bmRlcnZlcmsubm8=.txt wp-admin/d3d3LmR1bmRlcnZlcmsubm8=a.txt wp-admin/images/index.php wp-admin/ZHVuZGVydmVyay5mcmIuaW8=.txt wp-blog.php wp-load.php ./web/cpresources/b9382711/yii2/helpers/Inflector.php ./web/cpresources/b9382711/yii2/Yii.php ./web/dist/404.php ./web/dist/dashicons.php ./web/uploads/zr.php ./web/uploads/watchdoge.php ./web/index-clean.php ./web/images/wp-log.php ./web/assets/originals/new_readme.php ./web/assets/formtest/wp-aespa.php ``` We have also seen `index.php` files to be affected. ## Update Craft CMS Update the SEOmatic Craft Plugin to the latest version. Best also update all other plugins and Craft as well. We advice to start with your local installation and then apply the updates by deploying. Please see our [update Craft article](https://help.fortrabbit.com/craft-3-update) on how to do that best. Please mind that, even when your website is now updated and thus secured, it might have been target to attacks before. The update can not protect you form already existing hacks, it can only prevent hacks in the future. So even when you are up-to-date we recommend to check the files. ## Change the database password It's also a good idea to change your database password to make sure that no one has access to that any more. You can reset the MySQL password with our Dashboard, see our [help instructions](https://help.fortrabbit.com/mysql#toc-resetting-the-mysql-password). When using our dynamic environment variables resetting the MySQL password will be seamless, no configuration change on code level required. ## Remove malicious files If your App was indeed hacked, remove the malicious files that have been created by the introducers. Those files are not part of your Git repo. For Universal Apps you need to login by SSH / SFTP and manually remove all the files. ## (Wipe and redeploy) You might also wipe everything and redeploy a fresh state from your local copy to make sure all the bad stuff is gone for good. Please consider: Universal Apps have an [overwrite but not delete deployment strategy](https://help.fortrabbit.com/deployment-methods-uni#toc-git-push-overwrite-but-not-deletes), so you will first need to delete all the files by SSH/SFTP upfront. Make sure to keep your uploaded assets, but also make sure to check your asset volumes as well, since we have seen files in there as well. Pro Stack Apps have [atomic deployment](https://help.fortrabbit.com/app-pro#toc-atomic-deployment), so deploying code from local will wipe all files on the App. Also make sure that your local copy of Craft is as up-to-date (version and content) as the production one on fortrabbit. We strongly recommend to keep the two environments in sync. Our [Craft Copy](https://github.com/fortrabbit/craft-copy) tools helps. You can also use a new App to deploy to. Create a (trial) App, add it as an additional remote, deploy code, assets and database (Craft Copy can help here as well), later move domain. ## (Restore your App from a backup) Another option is to restore your App from an existing backup, this applies when you lost your local version or it is outdated. We offer backups for some hosting plans. The backup retention period goes back to 14 days, so a clean state in there can not be guaranteed. Please see our [backups article](https://help.fortrabbit.com/backups-uni) for more details. You can also use your local development environment as the backup base. ## (Change passwords for the Control Panel) To be on the save side, better also change all user passwords for accessing the Craft CMS Control Panel. ## A word on responsibility and service level Please mind that is not our service scope to monitor or patch the software of our clients. We don't know about the software you are using. We don't peek in your code without permission. Therefore we can not clean or update your Apps. We will also not be able to re-install older versions of your App. We are in this together. You, the responsible web developer and client. We as the hosting provider are doing our best to keep the infra running. You take care of the software you write and install. For more details, please see our [support policy](https://www.fortrabbit.com/support-policy). ## Action taken by fortrabbit We have extended our blacklists to avoid malicious requests with new learnings from these cases. This is not fixing the underlying issue but will stop most attacks against this vulnerability. We mailed all clients owning Craft CMS Apps that have SEOmatic installed. We are also monitoring our systems for unusual usage patterns. Some hacks - like crypto mining - are abusing our platform (high CPU usage) and can be detected by us. We will proactively contact clients one by one in such cases. We started to pro-actively remove certain affected files on some individual Apps and even also removing malicious parts in certain files, for example in `index.php`. This is a measure, we don't like to do, since we usually never directly interfere with client code. We did so for clients who have not reacted on our previous mailings on the subject. We don't know everything on the matter. We can not guarantee that this guide is a definite fix. We are also still learning here. We will update this article with new learnings. ## Further hearing The latest devMode podcast show called "[Critical SEOmatic SSTI Vulnerability Post-Mortem](https://devmode.fm/episodes/critical-seomatic-ssti-vulnerability-post-mortem)" discusses the issue in retrospect. # September 2023 updates Source: https://blog.fortrabbit.com/september-2023-updates Created: 2023-09-06 Author: Frank Lämmer Tags: chronicle > A platform update covering operating system components and newer hardware, with the version list, the schedule and the downtime. We are updating the underlying operating system layer components and moving to newer hardware. This platform update will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 60 minutes, but we aim for only a few minutes. We will run the updates sequentially, one App at a time, over the course of several days. The individual downtime per App will likely be less than 60 minutes. We cannot predict which App will be affected ahead of time. We plan to start with 'evening sessions' for Europe (CEST) and later with 'morning sessions' for US. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates and timing. We can not yet tell how many sessions there will be. We anticipate that the updates will spawn into October. Here is the complete list of client facing changes: ## PHP versions [https://www.php.net/supported-versions.php](https://www.php.net/supported-versions.php) - PHP82 (8.2.4) → 8.2.8 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_2) - PHP81 (8.1.17) → 8.1.21- [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_1) - PHP80 (8.0.28) → 8.0.29 - [changelog](https://www.php.net/ChangeLog-8.php#PHP_8_0) - EOL December 2023 - PHP74 (7.4.33) - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_4) - NO CHANGE, update soon, see below ## PHP Extensions (changes) - ImageMagick library (7.1.1-6) → 7.1.1-15 - [changelog](https://imagemagick.org/script/changelog.php) - mongodb (1.15.1) → 1.16.2 - [changelog](https://pecl.php.net/package-changelog.php?package=mongodb) - phalcon5 (5.2.1) → 5.3.0 - [release notes](https://github.com/phalcon/cphalcon/releases) - only for PHP 8.0, 8.1, 8.2 - blackfire php probe (1.86.6) > 1.89.0 - [list of current releases](https://blackfire.io/docs/up-and-running/update) - blackfire agent/client (2.14.2) > 2.21.0 - [changelog](https://packages.blackfire.io/binaries/blackfire/2.14.0/CHANGELOG) - newrelic php probe and agent (10.8.0.323) > 10.11.0.3 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ## Extended PHP 7.4 grace period At some point, we will stop supporting PHP 7.4. We do not have an exact date yet, but we plan to continue supporting it until the end of the year if no security issues arise, possibly even longer. If you have the time and budget, we recommend updating your Apps now. When you have kept your software up-to-date, the update should not be a problem. See our [PHP 7.4 EOL blog post](/php-74-eol) as well as our [PHP upgrading guide](https://help.fortrabbit.com/php-version-upgrade). There will additional communication from us. ## MySQL 8 required soon We have recently moved most Apps to MySQL 8 without problems. It turned out that a few Apps have problems and they have been reverted to MySQL 5.7 for now. It seems that most of them also run on PHP 7.4 and have outdated software installed, old versions of Craft CMS, Laravel, WordPress. There will be additional communication on that as well. # Small Dashboard improvements Source: https://blog.fortrabbit.com/small-improvements Created: 2015-04-30 Author: Frank Lämmer Tags: chronicles > Two small dashboard additions: batch importing environment variables from a .env file, and DNS checks on domain setup. > The details are not the details. They make the design. **Charles Eames** The big plan is our [PHPkind changing solution](/roadmap-to-hack-app), but we also care about the details. Therefore we have just published two minor platform upgrades in our Dashboard: ## Batch importing ENV vars Entering environment variables one by one is slow. That's why you now also can enter multiple ENV vars at once. The new ENV Var import option allows you to enter (read: copy/paste) a multi-line configuration file. ## Actual routing preview for domains DNS is hard. There are many different complex setup scenarios for registering domains. At least we can help by making it more transparent. Besides the desired CNAME target for your domain, the Dashboard now also shows the current life DNS routing target. So you can compare actual state with desired state. # Small team, big ideas Source: https://blog.fortrabbit.com/small-team-big-ideas Created: 2025-12-14 16:14:11 Author: Frank Lämmer Tags: chronicles > Five developers, no venture capital, competing with giants. A brain dump on motivation, project management and business philosophy. Our [new platform launched in BETA](/new-platform-beta) recently. That was a big milestone for us. But there is still a mountain of work ahead before we can drop the BETA label. We are competing with giants. No VC money to burn. We are just 5 developers. How do we even cope? ## Irrationality > They didn't knew it was impossible. So they dit it. It might not be as simple as Mark Twain puts it. But spinning up a reality distortion field and ignoring the odds helps. Maintain a childlike naivety to keep going. Don't get overwhelmed. ## Planning > Plans are useless. But planning is everything. Humans are bad at planning. Let's embrace that. We plan for the known knowns. We anticipate the known unknowns. And we expect the unknown unknowns to hit us hard anyhow. ## Ideas Good ideas are fragile and easy to miss. I file each new idea, keep it around, and revisit it after a while. A little distance often helps to see things more clearly. The best ones will stick. We prioritize together using a simplified RICE model (impact, confidence, effort). Good gut feeling (learned a lot from my co-founder Oli) and domain knowledge are helpful too. [Customer support driven development](/support-driven-development) helps separate signal from noise. Saying "no" is still hard. I got better over the years at turning fuzzy ideas into actionable tasks. ## Iterations Sometimes we have a good implementation plan, but it's too large or blocked by dependencies. Sometimes, we don't even know what the solution should look like yet. Project management helps breaking big ideas down into small tasks. We aim to get a first iteration out quickly. Then we can dogfood it, show it to customers, learn, and iterate. ## Time We are fortunate to have a stable financial situation. This buys us time, which is one reason we ship slowly. We are not a high velocity team and that is ok. But we need to be careful. Time is still our most precious resource. Our roadmap, projects, and features need to survive reality. ## Distraction > Keep calm and carry on coding. Don't look at the scary news in the world. Don't try to figure if AI will kill your industry. Don't compare yourself against competitors (just steal the best ideas). ## Lifestyle entrepreneurship fortrabbit is driven by our aim to create a good cloud hosting solution. We focus on engineering and product. We don't care about world domination or profit optimization. ## Staying healthy We try to avoid burnout and maintain a healthy relationship to our work. Our business should support not consume our lives. Work smarter, not harder. # Sneak peek Source: https://blog.fortrabbit.com/sneak-peek Created: 2016-08-22 Author: Frank Lämmer Tags: chronicles > What comes after the mission statement: a new hobby line alongside professional hosting, and the migration path for Old App owners. In our recent [mission statement](/mission-statement-2016) we analyzed the current situation of our hosting platform in relation to the PHP movement. We concluded to "respect the double-claw hammer". So, we'll continue expanding our professional PHP hosting line (New Apps), but we are also going to introduce a new: ### Hobby stack This new line will be suited for all small projects, from Laravel to WordPress. It's managed like shared hosting, but superior in quality. It's developer friendly, like VPS hosting, but without the hustle of server configuration. It's going to be a small container featuring Git deployment and native Composer support with a persistent storage and additionally also SSH/SFTP access. Sounds familiar? Yes, the specs read a lot like our [Old Apps](https://help.fortrabbit.com/old-apps). But the tech behind it is going to be different. We'll be using local storage, instead of network attached storage (not even EFS). So they are going to be faster than the Old Apps, but less scalable (which not required in most cases). They are also going to inherit other features from New Apps. An important design goal is an attractive pricing. We aim for **3 € per App** to get started. ### Migration options for Old Apps Old Apps (2013 stack) are in sunset phase now. Currently, clients can migrate from [Old Apps to New Apps](https://help.fortrabbit.com/migrating-old-new-app). While many are happy about increased performance and advanced features and workflows, some are missing legacy support and avoid the efforts of migration. We acknlodege that problem and we are happy to introduce a new solution here: The Hobby stack is going to launch before the Old App will phase out. That will make it also possible to **migrate Apps from Old App to the new Hobby stack** directly. The two stacks have much in common, so that the transition is going to be a lot easier. There are going to be two options to migrate Old Apps to: 1. **New App**: Professional, scalable, modern code base, 12-factor, web application, high traffic … 2. **Hobby line**: Backwards compatibility, legacy tech, website, low traffic … ### Timeline * Until November 2016, launch of the new Hobby Stack * Until January 2017, migration of Old Apps We have ideas to provide tools for semi-automated transition and maybe even offer hands-on service for the migration. This is the current planing (no guarantees). Please stay tuned for updates. --- ## Why we do this From feedback, support questions, activity statistics and screen recordings we have learned from and about our clients. They come from all over the world and have different backgrounds and goals. ### A lot of newcomers Our **general client** is an experienced developer with high coding skills, 30+ years old, from the UK, with a background in startup or agency. The **newcomer client** is looking for modern PHP hosting, seeking to learn and master new technologies, 20+ years old, from Asia, with a freelancer background — usually ends up not using our service: too complicated and too pricey. ### A lot of small projects Unlike Facebook or Wikipedia the majority of PHP projects is tiny in terms of hosting resources. They have very little traffic which usually that doesn't change over time. [Instant scalability](https://help.fortrabbit.com/scaling) is not a requirement. While there are small **web applications**, there are also a lot of small **pretty homepages**. Legacy technology and workflows are often involved here. So, some of our advanced features — like [12 factor design](https://help.fortrabbit.com/quirks#toc-ephemeral-storage), [Object Storage](https://help.fortrabbit.com/object-storage) and [App secrets](https://help.fortrabbit.com/object-storage) — are overkill. Some might doesn't need [Composer](https://help.fortrabbit.com/composer) or even [Git deployment](https://help.fortrabbit.com/git-deployment). And of course (and a little sadly), [pricing is important in hosting](https://blog.fortrabbit.com/what-the-hosting-and-the-meat-market-have-in-common). People take quality for granted and compare hosting by pricing. --- So this our way to bring **PHPower to the PHPeople**. We hope you like it. Your feedback is always, highly appreciated and welcome. # SSH Upgrade: PHP CLI and Git Source: https://blog.fortrabbit.com/ssh-upgrade-php-cli-and-git Created: 2013-02-18 Author: Ulrich Kautz Tags: chronicles > PHP CLI and git become available inside the SSH account, so artisan, the Symfony console and other framework tools run on the server. ## Work in the cloud So, what's your benefit exactly? If you want, you can give up your localhost now for good. With PHP on the shell, you can run your favorite framework CLIs directly in your App's SSH account. And there are many: * [artisan](http://four.laravel.com/docs/artisan) from [Laravel](http://laravel.com/) * [Symfony](http://symfony.com/) brings it's [console](http://symfony.com/doc/2.0/components/console/introduction.html) * Every framework using [Doctrine](http://www.doctrine-project.org/) comes with [doctrine-orm](http://docs.doctrine-project.org/en/latest/reference/tools.html) * [CakePHP](http://cakephp.org/) provides the [cake](http://book.cakephp.org/2.0/en/console-and-shells.html) command line tool * [Yii Framework](http://www.yiiframework.com/) comes with [yiic](http://www.yiiframework.com/doc/guide/1.1/en/topics.console) * [FuelPHP](http://fuelphp.com/) has [oil](http://fuelphp.com/docs/packages/oil/intro.html) (what else?) * [Lithium](http://lithify.me/) gives you [li3](http://lithify.me/docs/lithium/console) Of course, this is only the beginning. You can now use any Phar tool you like. For example [Composer](http://getcomposer.org/), which is already part of our deployment, can now be used in sub directories. Or have you heard of [Phing](http://www.phing.info/)? Great tool! But that's not all: Git on the console helps you with your legacy dependencies (that is: before composer) ⇒ use sub modules or private repos. Naturally, you still can use your localhost - but don't have to, if it's inconvenient. ## Limits Yeah, there are still some. Your App's SSH account is in a shared environment, and we have to keep up the quality. So you have limited memory (~300MB) and running workers is still not permitted. The alternative would have been to increase base-prices by a lot to assure we can pre-allocate sufficient resources for everybody. But hang in there, there will be dedicated SSH servers in our [Enterprise upgrade](http://www.fortrabbit.com/feature/enterprise-products). With those, you also can schedule cron-jobs and can choose how much memory you want. * [See the roadmap feature ](http://fortrabbit.com/feature/php-runtime-in-ssh) # Poodle Source: https://blog.fortrabbit.com/ssl-v3-disabled-poodle-vulnerability Created: 2014-10-15 Author: Oliver Stark Tags: chronicles > SSL v3 is switched off across the platform in response to the POODLE vulnerability. No action is needed on the client side. ## The poodle bite **tl;dr** We've disabled legacy support for the 18 year old SSL v3 protocol on our SSL Add-On and the free SSL endpoint on App URLs. There is no action required from your side if you are a fortrabbit customer. Yesterday, yet another SSL vulnerability has been discovered by three Google researchers. This one got the neat name POODLE (Padding Oracle On Downgraded Legacy Encryption) and allows man-in-the-middle attacks on secure connections which can lead to exposing sensitive data such as HTTP session cookies. The only safe way to mitigate those attacks is to disable the SSLv3 protocol either on client or on server or on both sides. Since clients do not (often) have control (or knowledge) of their used encryption protocols the deactivation on server side is the best approach. This is what we did today for all free SSL certificates and SSL AddOns. The downside of this measurement is that very old clients (yes, IE6 strikes again from beyond the oh-so-earned grave) are not capable of using up2date protocols like TLS v1.0 - 1.2 and cannot connect to servers providing only these. However, those clients are [increasingly rare](http://www.w3counter.com/globalstats.php) and from our platform statistics basically non-existent. If you want to make sure you won't suffer from the omissions of a lazy admin when browsing the interwebs: [here](https://zmap.io/sslv3/browsers.html) is an exhaustive guide on disabling SSLv3 for your browser. Or you can use an [online check tool](https://www.tinfoilsecurity.com/poodle) to verify that the site you are using is secured. ### Further reading - [Very good and in-detail explanation of the attack](http://blog.cryptographyengineering.com/2014/10/attack-of-week-poodle.html) - [Original blog post by Bodo Möller](http://googleonlinesecurity.blogspot.de/2014/10/this-poodle-bites-exploiting-ssl-30.html) - [PDF security advisor by Bodo Möller, Thai Duong and Krzysztof Kotowicz](https://www.openssl.org/~bodo/ssl-poodle.pdf) # Status update Source: https://blog.fortrabbit.com/status-update Created: 2013-11-27 Author: Frank Lämmer Tags: chronicles > Where the platform stands in late 2013: a new dashboard in the making, what shipped since launch, and what did not. Dear fortrabbit followers, this is an update mission status post. What's going on here and what is not? ### A new dashboard is coming We like to iterate and to bring small updates/improvements more often than a big bang once in a while. But some things have to be bigger and this is one is going to be really great. We have been working on it for a while: a new dashboard. We are revamping the UI and we are rethinking all workflows. Everything will be smoother, faster and more responsive. The new interface will also gain on the feature side. Among others: metric based alarming, a new and improved collaboration and lots of more insight in your App. But it's not only a new, shiny interface: it builds on the major rework of the backend which implements the learnings we've gained from the last year of service. The new dashboard in cooperation with the new core lay the groundwork for a new family of features to be released in the coming months: finally an API, a CLI for improved App runtime control, integration of 3rd party AddOn vendors, multi-region support and maybe even multi-vendor capability. ETA: [Q1/2014](http://fortrabbit.com/feature/enhanced-dashboard). ### The new deployment file A better way to control the deployment process to match the different use-cases of our users. ETA: [This Week](http://fortrabbit.com/feature/deployment-file) ### Dedicated MySQL Clusters Very soon you will be able to book your very own dedicated MySQL resources here. ETA: [Next Week](http://fortrabbit.com/feature/mysql-nodes) ### No Dedicated HTTP-Cluster Plans [for now] Actually we planned to launch new dedicated HTTP resources by the end of this year. We are not going to. We think the time is not right yet. It will cost us time and we have more demand for other features. ETA: [Unknown](http://fortrabbit.com/feature/php-cluster-nodes) ### No US-Launch light [for now] We are also postponing our US launch light. Mainly because we don't want to do it with the current [old] dashboard and backend. The US-launch-light would also keep us busy: more maintenance, more support. Before we scale our business, we need to master it some more. ETA: [Unknown](http://fortrabbit.com/feature/fortrabbit-goes-us) Please also see our [changelog](http://fortrabbit.com/changelog) for the latest changes. # Sunsetting a few features Source: https://blog.fortrabbit.com/sunsetting-a-few-features Created: 2014-06-18 Author: Frank Lämmer Tags: chronicles > The SMTP wrapper and the ReSync tool are switched off ahead of the new dashboard, with a note on how features reach end of life. Our [new dashboard](http://fortrabbit.com/feature/enhanced-dashboard) is in the making. There are going to be lot's of cool new features, but we also plan to skip some _not-much-used-not-so-good-not-so-future-proof_ ones for the first time. Here is what's going to happen and bit of **end of life philosophy**. **tl;dr** We are planning to **disable** our **[SMTP Wrapper](http://fortrabbit.com/docs/how-to/php/sendmail#smtp-wrapper)** (sendmail proxy) and the **[Resync Tool](http://fortrabbit.com/docs/essentials/deployment-workflows/resync-tool)** (Git/Webspace helper tool) by the **31st of August** 2014\. Please speak up now if you don't want that. ## Alte Zöpfe abschneiden The headline above is a German idiom and can be translated to: "cut of old pigtails" and means something like to get rid of old habits. Web hosting is a business that profits from your forgetfulness. Ask yourself: How many of your old websites are still running — PHP5.3 or lower? Yes on the one hand the hosting service should be as stable as a rock, backward compatible forever. On the other hand, we all want to get that new technology that came out last week in our hands, as soon as possible. Is it possible to run a managed cloud hosting platform that is future- and backward-compatible at the same time? It's not, so we need to find a good balance between accretion and erosion. Facebook moves fast and breaks things [with a stable infrastructure](http://www.cnet.com/news/zuckerberg-move-fast-and-break-things-isnt-how-we-operate-anymore/). Apple made their Mac operating system freely available so that people adapt the latest version faster. Major browsers get an automatic update every month, so you don't know the version number anymore. And even the Internet Explorer has a dev channel these days. Everyone is on a rapid release cycle now. So are we. We subscribed to progress. We encourage you to move with us. We want active and happy clients. We will communicate upfront with enough time ahead and clearly about changes. We will answer your questions, help you with migration, name alternatives and listen to your feedback. Of course we will also the platform stable, reliable, predictable and stable. We support the playful hacker in you, while respecting the business owner needs. ### About the SMTP Wrapper end-of-life Our SMTP-wrapper is a proprietary little helper tool to use the popular PHP [mail()](http://www.php.net/manual/en/function.mail.php) function on our platform. The background is, that just plain mail() probably won't work from the AWS network. In the **current implementation** you can enter SMTP access credentials in our dashboard to use mail(). We then will catch the mails from mail() within your Apps code and deliver them via SMTP. We are **skipping this feature, because** it's mostly for the benefit of novice users and we think you are more advanced. Also there were lot's of misunderstandings and problems setting it up. It is also not much used and there are good alternatives. **What you need to change** when you are using it: For Laravel or some other framework that abstracts mail sending: Use SMTP directly from the framework itself — that's a much cleaner solution. For Wordpress: there are plenty plugins to setup and easily use SMTP instead of mail — easy. For the sophisticated heavy user: Consider to use Transactional mails as a Service (like PostmarkApp, Mandrill, SendGrid …) — benefit from the benefits. Please change your code if needed until 2014-08-30, or raise your voice now. ### About the ReSync Tool end-of-life Our [Resync tool](http://fortrabbit.com/docs/essentials/deployment-workflows/resync-tool) is a proprietary deployment helper tool to get your Git and your webspace into sync (after you messed up). The usual use case is, when you used the update button in WordPress and then suddenly the code on the server is newer then your local one. And since web space and remote Git repo are not the same, you can not just pull these changes back in. We are **skipping this feature, because** it's not needed for our upcoming ephemeral (12-factor) Apps, it's a source of misunderstandings, it's not much used, it's a hack to compensate for bad practice and there are alternatives. **What you need to change** when you are using it: Don't mess up: plan carefully, use composer and Git and best practices. Our [deployment file](http://fortrabbit.com/docs/in-depth/deployment-file) is an alternative for syncing your local stuff up to the remote webspace. Please change your habits until 2014-08-30, or raise your voice now. ### BTW: About PHP versions We will incorporate new PHP versions as soon as we can. We will support old versions as long as there will we be security fixes for it. PHP 5.3 will be due within the next months (though we don't support it anyway). Given PHP's record, 5.4 will probably become unsupported sometime during mid 2016 , that's 2.5 years ahead. What do you think? What are your expectations? # Sunsetting freemium Source: https://blog.fortrabbit.com/sunsetting-freemium Created: 2014-03-18 Author: Frank Lämmer Tags: chronicles > The freemium development plan is replaced by a free trial. The reasoning, the timeline, and what it means for existing accounts. ## Freemium days are counted We have blogged about this [before](/freemium-or-free-trial), [before](http://blog.fortrabbit.com/free-web-hosting/), [before](http://blog.fortrabbit.com/freemium-vs-bootstrapped/), and even [before](http://blog.fortrabbit.com/the-freemium-hosting-business-models-our-thoughts/). Now we made a decision: Our freemium DEVELOPMENT app hosting plan will go away. We are going to have a free trial instead. Some of you have noticed that our free tier plan became very limited lately. Free slots were nearly not available. That was an experiment we have been running. We were curious what will happen when there is no free plan available. It turned out that conversions (free to paid) have been better - even when we stitched the boarding bonus (another way to try out our service for free). So we believe that cutting the freemium model will help us to focus on our real product and serve our real customers better. ## PHPower to the PHPeople It's not that simple. We have discussed about that a lot here. I personally don't want fortrabbit to be just a really good PHP cloud hosting service. I want to make an impact on the PHP community with fortrabbit. I want fortrabbit to become to PHP what Heroku is/was to Ruby. For me the true value of this **Platform** as a Service is not about technology, it's about the great people (you) using it. Let's push modern PHP web application development together. A free PHP cloud development environment sounds like an obvious fit for this. ## But… - real development is probably still better done locally (Vagrant rocks!) - our free plan had to be very limited (yes the freeze sucked) - supporting the free plan took a lot of time - we attracted a wrong crowd - just looking for any kind of free hosting ## For now… We are continuing our no-free-plans-available-now experiment to make sure this is not a short term effect and to listen to more feedback. We have updated the free App waiting line algorithms (more fair and transparent now). ## Soon… With the upcoming launch of our [new dashboard](http://fortrabbit.com/feature/enhanced-dashboard) (ETA Q2/2014 Q4/2014) we will introduce a new free trial method - apart from a lot of great improvements and new features of course. # Support as a Service Source: https://blog.fortrabbit.com/support-as-a-service Created: 2014-04-07 Author: Frank Lämmer Tags: chronicles > Enhancing our platform with professional & reliable developer to developer support. We offer a highly automated PHP cloud hosting solution. In theory our business run's on it's own: we don't have to interact for most of the time: the sales process is handled by the dashboard, our watchdogs and daemons are spinning up new servers. Well, in the past two years we have learned how important the human factor is. Customer support is a cornerstone. Supporting our users helps us in two ways: **Increasing sales** -It's much more likely that a happy user converts to a happy client. **Understanding **- There are many ways out there to measure user behaviors, but speaking to people really makes a different. It's the best way to learn what they expect from you and where are they coming from. Well, this kind of founder support is a [not-scaleable-thing](http://paulgraham.com/ds.html). With increasing popularity more and more support requests come in. Users had to wait longer for an answer, which was probably written quickly by us — just needed more time to get to it. The [lately announced switch](/sunsetting-freemium) from freemium to free trial already reduced our workload — but still, we feel that our support quality wasn't up to the standards we want to uphold. We know that you rely your business on us. For this you need high **quality of service** for support as well. That's why we are now, [as announced](http://fortrabbit.com/feature/support-as-a-service), offering [premium support plans](http://fortrabbit.com/solutions/support) in three different flavors. ### What you need to know The premium support plans help you with your business. They are an optional upgrade. You can book a premium support plan from the new Support tab in the dashboard. The free support is still available, you can still file a ticket as usual. However premium support plans include more services like: launch support, in-depth problem diagnostics, App monitoring - plus a guaranteed response time on your tickets. The URL for filing tickets has changed, it used to be: [fortrabbit.com/docs/support/file-a-ticket](http://fortrabbit.com/docs/support/file-a-ticket), now it's: [my.fortrabbit.com/support](https://my.fortrabbit.com/support). This means you need to be logged in to file a new ticket. Our ticket system is the best way to get support. Ask quick questions on [Twitter](https://twitter.com/fortrabbit), ask platform related questions on [Stack Overflow](http://stackoverflow.com/questions/ask?tags=fortrabbit). Call us if you want to speak to a human. We hope you like this and are of course curious what you think. # Support driven development Source: https://blog.fortrabbit.com/support-driven-development Created: 2024-08-27 13:11:39 Author: Frank Lämmer Tags: webdev > Doing first-level support and product ownership at once: how client conversations turn into features rather than just bug reports. I wear many hats at fortrabbit. I do most 1st level customer support and I am also product owner. These two roles go together well, since I have a direct channel to what developers are expecting from us. Exchanging with our clients not only helps to uncover bugs and UI quirks. We also learn how they see our platform. And that is often a brutal truth. Some of our features build with best intentions are not well received. The customer is always right with some string attached. 'Customer support driven development' is not a new concept of course, this is how we practice it. ## Support meetings We have rotating support shifts. Everyone in the team needs to do at least a bit of support. Once a week, we do a support meeting to reflect on recent cases. Personal bias: I will likely cherry pick customer cases that are supporting my vision. Support meetings help to exchange on how we perceive the feedback. Feature requests may be added to already existing tickets in the backlog, or we create new tickets. We let update clients on their requests even after longer periods of silence. ## Noise to signal Customer input helps us to validate our work on the [new platform](https://new.fortrabbit.com) in the making. Picking the right signal and turning it into functionality is not an easy task. Most ideas will be dismissed, we need to say 'no'. Generalization VS specialization: Customers present us with their problems and requirements. Our job is to figure if implementing a specific idea will support more might be of general interest. It's easy to take customer feedback too literal. Often customers request faster horses. But our job is to build a car. We need to think ahead, outside of specific constrains. A common request is yearly upfront payments. We however have pro-rated billing after usage (not upfront), which supports making experimenting with different hosting setups and scaling easily. So we need to keep educating customers about the benefits of such a system. ## Supportive clients We are grateful to have such awesome clients who are really invested in our platform and are helping us to uncover potential. # Support pages are on now Source: https://blog.fortrabbit.com/support-pages-are-on-now Created: 2012-08-15 Author: Frank Lämmer Tags: changelog, chronicles > The first fortrabbit help pages go live, and the search for a knowledge base system that suits a small hosting company. UDPATE 2014-10: We have switched support to [help.fortrabbit.com](http://help.fortrabbit.com) — using our on slim PHP system. - - - - The help pages for our (upcoming) PHP PaaS are basically kind of ready. Well, you know - the lean way. Have a sneek peak: * [support.fortrabbit.com](http://support.fortrabbit.com/) ## Finding the right help system We have finally decided to use [desk.com](http://desk.com) (formally Assistly) for our support and documentation. We have been poking around with this for a long time. The [help for our old service](http://hilfe.frbit.de/) was based on a wiki engine. This wasn't so bad, but we wanted something new and Wikis are somehow last century. Our original idea was to create an own solution based on Ulis light weight [zerocms](https://github.com/ukautz/zerocms). This way we would have been able to edit articles directly in the text editor in markdown synatx and manage changes simply with Git. But this would not have included a search and no feedback. And we don't want to reinvent the wheel for everything we do nowadays. So: Desk.com is ok, but it's a bit overloaded for us. We are not quite sure if we really need all the fancy support desk features. The WYSIWYG editor in the knowledge base really sucks of course. Looking at other Startups shows me that they have a hard time with their user documentation/manual too. Advantages of such a SaaS help desk are: an integrated search function and feedback/reaction tools for users. Well, maybe something really slim based on [Jekyll](http://jekyllrb.com/) or [zerocms](https://github.com/ukautz/zerocms) would have been better for us. # Survey results Source: https://blog.fortrabbit.com/survey-results Created: 2015-05-12 Author: Frank Lämmer Tags: webdev > What customers said in a survey about fortrabbit and about hosting in general, and which conclusions were actually drawn from it. ## Thanks for your answers! We have just asked you a few questions about our service and hosting in general. Everybody hates surveys. But it's important for us to get to know you a little better. It helps us shaping the future fortrabbit. Here is what we have learned and what not: ## Results Just in case you wonder: most question allowed multiple choices, that's why some totals are more than 100%. ### Get the word out on Twitter We asked our Twitter followers to take the survey. We "reached" around 1,700 PHPeople and got around ~30 answers from that. Ok. ### E-mail marketing We also did an email campaign to 13,000 of our users. It had an open rate of 25%. We got around ~180 answers from that. Learning: A newsletter is a reliable way to get answers in. But around 200 mails for 1 answered survey is a lot of waste. ## Asking the right questions is hard We have discussed the questions internally before publishing of course. My personal premise: > The way you ask the question is much about the answers you will get. We are especially looking for indicators on a new pricing strategy. So we have asked what is more important, "price" or "quality of service"? You could answer with a range-slider from 1 to 10. The average answer, as you could guess: **5.57**. Of course everybody wants to have perfectly-balanced price-value. I would like to rephrase the question like this: **Which hosting package would you buy?** 1. 99% uptime guarantee for 5 € 2. 99.9% uptime guarantee for 50 € 3. 99.99% uptime guarantee for 500 € I guess not everybody would take the good balance. But what, if we phrased it like that: **Which hosting package would you buy for 5 €?** 1. supreme performance, but not guaranteed availability 2. average performance and alright availability 3. rather low performance, but very high availability Those 5.57 can go both ways. Our take: People are aware that cheap comes not free. ## We got contradictory signals We already knew that people value speed as an important indicator for choosing their hosting provider. The background: Currently our free trial is our smallest plan. We are now considering a new trial which comes with far bigger resources, so that the actual performance can be experienced. The problem with starting on a small plan is that you might not get what's possible. I personally believed that performance bottlenecks will mostly be found in production, after you already moved your application to your provider. Checking out the speed of a new web host is tedious - I figure really few would actually do it. On our platform we are seeing most people using the trial App to check out the deployment and run a simple `hello world`. So we asked the questions: **1. How do you measure the speed of your new web host?** So it turns out that most of you PHPeople do test the speed. **2. How fast is fortrabbit?** Well, most of you didn't test it - which contradicts the previous result and left us non the wiser. ## Interpreting the answers is hard Now what does the above teaches us? I would argue that if we have phrased the first question differently, we would have become different answers — "Do you test the performance" instead of "How do you test performance". I think the second answer is the real one — people don't test hosting provider performance upfront. You could also argue that not everybody is a fortrabbit client (yet), so that's why they haven't tested the speed yet. Or you could argue that people want to test the speed - but don't. ## Geo-prejudices As a company we need to be oriented on profit. Being based in Europe, it's not surprising that we make most revenue with clients from northern Europe. Also, maybe a bit surprising, is that there is indeed a a lot of interest in our service from Asia. Our general assumption was: In lower-income countries our pricing is a bigger issue. To confirm this we geo-tagged the survey. Learnings: About 10% asked for a more affordable pricing structure. As it turns out, they came evenly distributed from Asia and Europe/US. About 5% asked for "free hosting". Here the majority came from Asia. Of course we are not going back to that (again): It simply does not work. ## Other learnings The last question was "What are you missing at fortrabbit?". Again, we wanted to check out if we are on the right track or if we are missing any trends. Most answers are very individual, feature X, feature Y, feature Z. Too many features making us too flexible and versatility are hard to tackle with our small team. But we are aware. The Bitbucket integration request was repeated. Why Bitbucket and not GitHub? Bitbucket offers private repos for free ;) ## Notable feedback > Somebody to proof read your documentation. More transparency about the actual app and what you get. A CLI. An API. Thanks again to everyone! # Take off Source: https://blog.fortrabbit.com/take-off-fortrabbit-php-platform-launched Created: 2012-10-04 Author: Frank Lämmer Tags: chronicles > fortrabbit announces general availability of its PHP hosting platform from Berlin, and the problem it was built to solve. **Berlin, 2012-10-04** - We, fortrabbit, are thrilled to announce general availability for our new PHP platform hosting services. ### Which problem is solved? All the stuff in the interwebs has to be hosted somewhere. Enterprise companies have their IT department to handle such things. In smaller structures such as agencies, startups and of course for lone freelancers this can be a major problem. Developers want a modern development environment, a reliable infrastructure, established standards and an up2date run-time. But they want to focus on their code and don't have the time or the skills to set it up and maintain everything themselves. Or they are simply fed up with mundane, repeating sysadmin tasks. ### Who should care? - The new PHP Renaissance There are only two type of programing languages: The ones nobody uses and the ones everybody complains about. PHP is definitely one of the last type. Nonetheless it is still the most popular for web related development - with more than 300 million websites using PHP. The community is pushing forward towards new and promising trends and technologies. Recent PHP upgrades brought mighty core improvements and allow PHP developers to go eye to eye with any other modern web development language. Our platform supports this new approach. We encourage - not enforce - to use modern technologies and possibilities. But we also take care about backward compatibility and do not discard established standards - just because we want to look modern. ### Hey wait - you are not the first cloud hosting platform! True. There are some others and even some more are coming. We see this as a proof of an actual need and believe that there is enough space for multiple PHP platforms. Developers have different skill levels and flavors - soon they will be able to choose the platform they like the most. ### What about Features? - Full featured free development environment - Easy to use yet powerful web control panel - Valuable performance metrics - Instantly scalable without code adjustments - Consumption based pricing model - Read-write file system - Access with Git, SSH and SFTP - Native PHP composer integration ### What's PaaS? - explained to Non-Geeks When relatives ask us what we actually do here, we answer with an allegory: Where to rent an apartment? The cheapest offer is a plattenbau, 50 square meters, urine soaked elevator, paper thin walls. That's shared hosting. Most expensive is to hire a real estate broker to find the perfect mansion matching your needs (the private yacht harbor). That's managed hosting. And then there is also everything in between. PaaS offers you a wonderfully modern apartment - but you can change it's size, the number of rooms, the equipment and even the location at any time. You pay an affordable price only for what you really use. That's Platform as a Service, that's what we do. ## About Fortrabbit ### Profile We are a bootstrapped startup from Berlin, run by three co-founders Ulrich Kautz (technical lead), Oliver Stark (coder) & Frank Lämmer (concept/design). We develop technology based solutions and web services. ### History Our old hosting service included new technologies in a standardized environment. The new platform brings essential standards and even more new technologies to the cloud. All the websites we have been developed had to be hosted somewhere. In 2006 we put all them on a dedicated server. The unused webspace was filled up with our own projects. Some friends also asked for hosting. The next server was rented. This went on. In 2007 we decided to take all this more serious. We (Ulrich & Frank) founded • fortrabbit and bought some metal pizza boxes. To achieve consumption based pricing and scalable ressources we developed a highly virtualized infrastructure architecture for our stack. A little private cloud, secure and versatile. Our own control software MISH offered a nice web frontend for clients. We also integrated a complete billing solution ([WebRechnung](http://webrechnung.info)). But the MISH system had two problems: The great range of functions made it very complex, maintining the bare metal was a hassle. So by the end of 2011 we decided to make a cut: Take all of our experiences and realize a new system in the cloud. Now, only 10 months later, after a short private BETA period, the all new fortrabbit - PHP Platform launched. # Green cloud? Source: https://blog.fortrabbit.com/the-cloud-economically-attractive-but-what-the-about-ecological-impact Created: 2012-10-23 Author: Frank Lämmer Tags: opinion > The cloud: economically attractive, but what the about ecological impact? In May 2011 Greenpeace asked: [How dirty is your data](http://www.greenpeace.org/international/Global/international/publications/climate/2011/Cool%20IT/dirty-data-report-greenpeace.pdf)? Big cloud players like Apple, Google, Facebook, Twitter, Microsoft, Amazon and others where given bad grades. Data centers consume a lot of power and have to be cooled. The Greenpeace campaign is still [ongoing](http://www.greenpeace.org/international/en/campaigns/climate-change/cleanourcloud/). Some brands have reacted and are changing for the better. There are data centers powered by solar energy and there are data centers in Iceland cooled with outside air. The underlying infrastructure layer for [our platform](http://fortrabbit.com/) for example is provided by the Amazon Web Services. It's a great service, in terms of technical implementation. We love it. But it scares me a bit that i could not find any environmental facts on AWS. Is this hi-tech eventually powered by last century energy sources? [Mr. Vogels](http://www.allthingsdistributed.com) and Mr. Bezos: Please consider that customers care about green IT and ethical commerce. Most airlines already realized optional carbon offset for flight tickets. # The freemium hosting business model Source: https://blog.fortrabbit.com/the-freemium-hosting-business-models-our-thoughts Created: 2012-08-02 Author: Frank Lämmer Tags: opinion > Will small hosting plans end up free? Someone always pays for the resources — a look at freemium in hosting after AppFog's pricing. **tl;dr** Will most smaller hosting plans be free in the future? We are not quite sure, hosting is about resources, someone always has to pay for them. Congrats to our PaaS colleagues at AppFog. They recently announced GA (general availability). The big news was the [pricing](http://blog.appfog.com/if-paas-is-expensive-and-slow-why-not-use-a-vps/). They offer a generous free plan. You can really run your website/service for free there. They claim that this is similar to hosting as the emerge of Gmail (with some Gigabytes of storage vs Hotmail with some Megabytes) was to free mail. It's true: Gmail changed what we expect for free from a free mailing provider (I know a lot of freelancers who use an e-mail address from Gmail - even for their business). But can this model be applied to web-hosting as well? Imagine that you want to run your eCommerce site or some other serious business - would you really trust a free service for this? They don't know who you are, they just got your e-mail address and they won't guarantee for uptime (everything for free comes without a guarantee). So you can't claim for availability. You don't have support. And you don't know if this free is going to be free forever. Probably I am a bit jealous of the great new offer. Of course we will have a free plan as well. But it won't be that splendid. We are not funded, so we don't really have a marketing budget. We are bootstrapped. And just like 37siginals, we don't believe in losing money to gain clients. And a PaaS isn't just software. It's about hardware resources. And those need to be paid. Our underlying infrastructure provider AWS is not giving us anything for free (in fact they offer a 10% discount starting at 250,000.00$). So it's not only that our free customers use our software and hosting environment with automated failover, easy deployment and whatnot that we have build for free - they also use the infrastructure for free. Some people say that cloud computing will reduce costs for hosting. That is true, but even in the cloud there are servers and hardware somewhere. Computers are getting more capable but electricity is not going to be free in the near future i guess. Of course we don't have a GeoCities business model where you could have free hosting in return for ad banners on your site. And of course our clients will not be the product here, we won't sell their data. Like in any other freemium model, our paid plans will have to balance the costs for the free plan. We give a piece of the pie away for free, because we want to show everyone how cool our service is and also because everyone else is doing so. We calculated very carefully what we can give away for free and we hope that we can loosen some limitations in the future. Our free product will be about development. It will be more than just a trial, it will be something you can really work with. We are proud of it. # Decoupled hosting Source: https://blog.fortrabbit.com/the-idea-of-decoupled-hosting Created: 2012-12-31 Author: Frank Lämmer Tags: opinion > Code in git, dependencies in Composer, assets in object storage, mail in a service: the case for modular, decoupled hosting. **You are one of the cool web kids?** You like [flat design](http://speckyboy.com/2012/12/11/the-flat-design-aesthetic/), use [preprocessors](http://css-tricks.com/musings-on-preprocessing/), your code is under [version control](http://git-scm.com/), you install components with a [dependency manager](http://getcomposer.org/) and your code is based on a **[decoupled** framework](https://github.com/illuminate). You call your websites Apps and host them on a new PaaS (such as [ours](http://fortrabbit.com)). But your domains are registered where again? And where are your e-mails hosted? ### Web service Monolithic frameworks are out, component based collections like the new Laraval 4 and Symfony are a better approach. I believe that the same light weight set up could apply to our hosting and web services as well. The old price dumping mass hosting services [sucks](/what-the-hosting-and-the-meat-market-have-in-common) and must be replaced. There are great new specialized services for your needs: * **Simple CMS**: [Squarespace](http://www.squarespace.com/),[ Virb](http://virb.com/) … * **Portfolios**: [Cargo](http://cargocollective.com/), [Carbonmade](http://carbonmade.com/) * **Blogging**: [Wordpress.com](http://wordpress.com), [Tumblr](http://tumblr.com), [Blogger](http://blogger.com), [Scriptogr.am](http://scriptogr.am) * **eCommerce**: [Shopify](http://shopify.com), [Big Cartel](http://bigcartel.com/) * **Static Pages**: [GitHub](http://github.com), [Amazon S3](http://aws.amazon.com/s3/) * **Personal Splash Pages**: [Zerply](http://zerply.com), [About.me](http://about.me), [Falvors.me](http://flavors.me/) * **Professional Developing**: [Heroku](http://heroku.com), [Appfog](http://appfog.com), [Dotcloud](http://dotcloud.com), [Pagodabox](http://pagodabox.com), [Cloud Control](https://www.cloudcontrol.com/), [Fortrabbit](http://fortrabbit.com) and even [more](/comparing-cloud-hosting-platforms) But to have your business up in the interwebs you will most likely need a memorizable addreess, a TLD. And you might also need to send and receive mails from this address. All the services above offer you a way to connect your domain, but that's it no service will host your domain nor your mails. So where to go then? In decoupled thinking domain and e-mail are two different things. So we are looking for two services: One to order and transfer domains and to manage DNS settings. One to set up and configure new mail addresses and to receive, SPAM filter, store and send mails from. ### Domain service It's really hard to find a service that does only domain hosting out there. Domains are usually not a product of it's own. They are often part of old school hosting plans, you know the ones that start with _check domain name availability now_. However some hosters offer dedicated domain (and mail) packages. Luckily there are some new specialized services: [iWantMyName](https://iwantmyname.com/) and [DNSimple](https://dnsimple.com/) just doing domain management. Both services match perfectly to decoupled thinking and the above services. In Germany [United Domains](http://united-domains.de), [Schlundtech](http://schlundtech.com) are also single purpose domains registration services, a bit more old school. [Domain Factory](http://www.df.eu/de/e-mail-hosting/) and [Host Europe](http://www.hosteurope.de/Domain-Mail/) offer packages with Domain AND Mail. ### E-Mail service That's more complicated. E-Mail hosting must be very reliable, SPAM has to be handled. The big elephant in this room is Google with [Apps for Business](http://www.google.com/enterprise/apps/business/) - that's just like Gmail, but for your own domain. Google is international and will probably never go down. It also comes with extra features: Calendar, Docs and Drive. There was even a freemium entry level, but the have just recently [skipped](http://techcrunch.com/2012/12/07/google-kills-free-google-apps-for-business-now-only-offering-premium-paid-version-to-companies-of-all-sizes/) that. Let me guess: They already destroyed the market and rule it now. Left competitors are: [Zoho Mail](https://www.zoho.com/mail/), [Rackspace Email](http://www.rackspace.com/apps/email_hosting/rackspace_email/), [Fastmail](https://www.fastmail.fm/) (all in the US). The usual extra business features for business e-mail are fine, but i am not quite sure if i will need them right now. ### Conclusion I would like to see more specialized professional services for domain management and especially for email hosting - **E-Mail as a Service** and **Domain as a Service** offers. Our old hosting system MISH included Mail and Domain handling. These things kept us busy, so i am actually pretty happy that we don't have to care about all this again on the new platform. As the old system is closing in April 2013, i have to tell our existing clients how to go on now. Some of them might proceed with classical hosting, that's ok, see my [previous post](/where-to-host-my-website-now) for this. Others will hopefully migrate to the new platform. I would like to give them directions like this: »We are your web hosting partner, register your domains there, host your mails over there. All services are separated but fit well together.« # New boarding bonus Source: https://blog.fortrabbit.com/the-new-boarding-bonus Created: 2013-10-31 Author: Frank Lämmer Tags: changelog > The boarding bonus experiment gave new accounts extra credit for a longer test drive. How it worked, and why it ended. UDPATE 2014: Boarding Bonus is not available any more. - - - - We have just released the new [tasklist](/the-new-tasklist) lately. Now we optimize the boarding process further with a new experiment: The boarding bonus - an extended test drive. Now, new accounts have the possibility, for 14 days after sign up, to get an extra credit, of 25 €. To claim the Boarding Bonus users need to enter their payment credentials - opt-out is possible of course. This is a great way to check out some of our advanced features - such as the [workers add-on](http://fortrabbit.com/docs/in-depth/workers). More infos can be found [here](http://fortrabbit.com/docs/how-to/misc/boarding-bonus). Thanks again for flying with fortrabbit. # The new Dashboard is here Source: https://blog.fortrabbit.com/the-new-dashboard-is-here Created: 2015-02-25 14:00 Author: Frank Lämmer Tags: changelog > The new fortrabbit dashboard ships after more than a year of work. What changed, what it cost, and where the roadmap goes next. ## The new fortrabbit It took longer than anticipated — more than a year from planning until launch. And it's a bigger update than we first anticipated. We have been in stealth mode working quietly for quite a while now — hopefully not too long. We have shifted our original roadmap to fully concentrate on this release. But now it's here. Finally. Release. Step into the light. ## Good got gooder This is an optimization release — no REVOLUTIONARY features nor technologies. Everything is just smoother, more stable, some early design mistakes fixed. The focus was to harden the system. Our clients use fortrabbit in production. The Dashboard should reflect this. It now feels more robust and more production-ready. Behind the scenes, there is much more. This update includes all the groundwork for our upcoming changes. The backend is more maintainable, manageable and scalable for us. ### Enhanced collaboration The most notable changes are made in the area of team work. Our new and unique [collaboration solution](http://help.fortrabbit.com/collaboration) maps real world working relationships for startups, agencies and freelancers. We hope you like it and make heavy use of it. ### Different support model We must acknowledge that we could not serve all clients with the same high level of support in the past. So we have made some strategic changes [here](http://forttabbit.com/support). Support is tricky. It turned out to be a good sales channel for us as people really appreciate that kind of help on a personal level. But it's also a lot of work. Like most SaaS and hosting services, we have hidden the support costs in the general fees. On top of that we offered "premium support plans". We have clients leveraging the general support and we have others using fortrabbit as a self-service platform. We now (hopefully) have a better offering for both groups: **Help yourself**: Our updated [help center](http://help.fortrabbit.com) is better structured, it's better integrated into the Dashboard, has more up-to-date content, on a higher level. **Get support**: We have dramatically lowered the entry level prices for professional support plans by 600%!!!! — the entry level prices for professional support plans. It's really affordable now. We haven't seen something alike elsewhere. On top of that we now offer a Professional Support trial period. That's crucial. Most support questions statistically get asked in the first weeks. So boarding and migrating is still handled with special personal care. Yes, we took away the included free support. So far it is an experiment. Maybe it rocks, maybe it also doesn't scale? Who knows. We hope you understand and like it. We are really curious on your feedback on this. ## Looking ahead We will now fully concentrate on our next generation of Apps — project **Hack App**. This will be our big bet in 2015. The goal is to crack the impossible. A new architecture to make the Apps faster, more stable and at the same time even more affordable. In other words: Fast, Good **and Cheap**. # New tasklist Source: https://blog.fortrabbit.com/the-new-tasklist Created: 2013-10-07 Author: Frank Lämmer Tags: changelog > The tasklist replaces a plain freemium tier with something fairer and more playful, based on measured behavior of new accounts. We have been watching you. Not you personally, of course. Besides qualified and [quantified feedback](/fortrabbit-user-survey-results) rounds we have been measuring your (our users) behavior on our platform. These learnings resulted in a new experiment: The tasklist. We want to higher your engagement and give you a better experience when using our platform in the right way. In other words: Here comes a more fair and more fun freemium model. ## About freezing > After a certain time of "inactivity" we automatically "freeze" free Apps. Frozen Apps are no longer available, but the data (web+mysql) is archived and can be "unfrozen" with a click in the dashboard. In the App overview in the dashboard you can see when your App will freeze. To avoid freezes you can reset the countdown timer in the dashboard at any time, or you can just upgrade to a paid plan. We [know](/freemium-or-free-trial) that these freezes suck. It's true: Our free tier is not as good as we would like it to be, our aim is a valuable free development environment. But it is essential for us to balance our freemium and the paid plans. Otherwise we be spending lot's of computing resources for tons of "it works!" pages. We know that you hate the freezes. But interestingly most of the freeze complaints came from users looking for [free web hosting](http://blog.fortrabbit.com/free-web-hosting/). To this we must say: We don't want to be such a service. ## A new model [Gamification](http://www.codinghorror.com/blog/2011/10/the-gamification.html) is everywhere. Now also on fortrabbit. Free Apps now include a "tasklist". Perform certain optional tasks and get more time until your App freezes. Nearly two third of our freemium users don't use Git, they'll just use SFTP (or maybe SSH). This is ok, we are just encouraging not enforcing you to use best practice. But the point is that you will have the best experience when using our fast and easy [Git push deployment](http://fortrabbit.com/docs/essentials/deployment-workflows/git). So obviously nearly two third of our paid users (AKA clients) are using Git deployment. You will probably even have more fun here when working with our super cool [Composer Git hook](http://fortrabbit.com/docs/in-depth/git-hooks/composer). So you will also get some extra time for doing this. Further more we will value when you [route a domain](http://fortrabbit.com/docs/in-depth/domains) to your App. ### In other words Your recently created plain vanilla free App will freeze much sooner, but as soon as you really using it, you will get more time as before. ## Further thinking Please expect that the timing of the freeze bonuses will change in the future. We will see how good it works out and experiment with it. We will also add a "boarding bonus" soon. Here you will get credits for entering your credit card credentials. It's a kind of a opt-out free trial, where you can also test other advanced features like our workers our memcache Add-Ons. We hope you like this new 'feature', please tell us what you think. # The Roadmap Source: https://blog.fortrabbit.com/the-roadmap Created: 2012-11-19 Author: Frank Lämmer Tags: chronicles > The fortrabbit roadmap for the coming year, written at the point where a young PHP platform decides what to build next. According to Ray Kurzweil, we are in the **»Leveling Off Phase**«. I think we all agree that technology is moving fast these days. For us it is a real fun ride to see new web technologies popping up each day. And it is even more fun to be a (small) part of it - pushing things forward. Our platform enables PHP developers to be more productive and to do better things in shorter time with more comfort. > By 2009, computers will disappear. Displays will be written directly onto our retinas by devices in our eyeglasses and contact lenses. Ray Kurzweil Software is never ready and never perfect. We are developing our still young PHP platform further. We are able to adapt cool new technology early, but we care about the overall experience. Even with a technology based service - such as our hosting is - we believe that "feeling" and "experience" are more important than "features". Our aim is to fit your real world needs of a PHP development and hosting environment. To make sure that we are on the right, we would like to show and discuss the next steps with you. # The story of our new invoice number format Source: https://blog.fortrabbit.com/the-story-of-our-new-invoice-numbers Created: 2020-02-03 Author: Frank Lämmer Tags: chronicles > How our new invoice numbers are structured and what went wrong when we rolled it out. ## What we have changed We just changed the number of the invoice. The old format was like `fr191112abet` while the new format is like `fr-2020-01-133-15-de-t`. Everything else stays the same. A minor update actually. ### Structure of the format ``` fr > for fortrabbit 2020 > year 01 > month 133 > client number (not reference) 15 > invoice per client de > country t > if an invoice includes taxes or not ``` ## Why changing the invoice number at all The main reason for the change was to correct the month within the old invoice number. We have consumption based billing. Invoices are getting created at the end of the month. The date on the invoice is always the last of the month. The service period is the month itself. With the old numbers, the month matched the actual creation date, which always caused confusion with book keeping. Now, with the new numbers, the month in the number matches the service period. While we had to adjust the number, we thought about what else we might change to make things more clear. Often invoices numbers are cryptic and not readable for humans. We believe in transparency. So we wanted the opposite: A speaking invoice number. We have long planned this change to happen with the first invoice in the new year. ## What went wrong on roll-out As you can imagine: An invoice number is something that is not easily testable, also something one might not consider to break things. The new invoices where correctly created and everything looked good, until the payments for the service period January came in. The bounce rate was unusually high. Almost half of the invoices where bounced. Now, when an invoice bounces, we immediatly send out a warning to the client that they need to take action. This alarmed a lot of the good clients and we got a ton of support requests. We soon found out what the pattern was. The new invoice format is longer, up to 23 characters. While filing the payments with the credit card payment system (WireCard), one of the fields of the payload is an identifier consisting of the invoice number and a time stamp. The new combination was in some cases (when including the `-t` string to indicate that the invoice has taxes) too long and could therefore not be proceeded by the payment gateway. We implemented a fix, rolled it out and retriggered the missing payments. So the issue was solved within hours. ## What we learned We blame ourselves for not thinking this through enough, of course. It was an annoying mistake that caused trouble and mistrust with our clients. On the other hand, we have actually planned this well. Even when would have been reading the API description against the new usage, we might would have missed it. There is some sandboxing, but it's not complete. The dummy data might have not revealed the issue, since the client numbers would have been to low. So unfortunatly: > There is no test like production. Not what we like. But reality. ## In closing Apologies to all affected clients one more time! # New write protection Source: https://blog.fortrabbit.com/the-story-of-our-new-write-protection-feature Created: 2013-03-21 Author: Frank Lämmer Tags: chronicles > Write protection reduces the privileges of a running app, and it is worth enabling on every production app. Why it took a while to build. **We have a new feature: Write protection for Apps.** Secure your Apps by reducing access their privileges. We strongly advice to enable this mode for all your Apps in production. This is the story why it took a bit longer to implement it. Read about how you can use it [here](http://support.fortrabbit.com/customer/portal/articles/1052580). We are a tech company with a twist for philosophy. These are two of our company main mantras: #### Encourage best practice We really like the way our great PaaS forefather Heroku **enforces** their users to use best practices (like Git deployment). However, we are more softcore. We like to **encourage** our users to use best practices. In other words: We support your habits. On fortrabbit you deploy code the way you deem best. We believe that standard compatibility is utterly important. Of course we offer modern tools and techniques (like Composer) for the most sophisticated workflows. And we like you to give them a try with us, if you haven't used them before, in the hope you will find even better ways to reduce your workload. Our support pages and our interface help you to get started quickly. #### Security first Whenever we have to make a design decision between security and something else (usability or performance for example), the former mostly wins - as long as it does not prohibit any level of usage, that is. We strongly believe that we, as your trusted cloud hosting vendor, have to take security VERY seriously. For example: we decided to use a very strong encryption for all the service (SSH/SFTP, MySQL, ..) passwords via one-way hashing. As a result not even we know or can access your passwords. However, this comes with two usablity downsides: 1. You cannot read out your service password in our dashboard, if you lost it, you can only create a new one. 2. Most other PaaS providers give you the MySQL [credentials via environment variables](http://stackoverflow.com/questions/12461484/is-it-secure-to-store-passwords-as-environment-variables-rather-than-as-plain-t). Granted, very handy. But it requires to save the password somewhere in plain text, so we can't do it. ### Writable Storage Most other PaaS don't offer writable storage and thereby have no need to make it accessible by any kind. When you deploy your App, it get's copied to the different nodes it is served from. In terms of usability and compatibility we think this is well below ideal. Our users should be able to use their favorite workflows, frameworks and CMS, without jumping through hoops. There should be no hacks needed to run a standard software such as WordPress. That's why we provided a shared storage for each App, to which you can deploy your App with Git - but also via SSH/SFTP. However, there is also another usability need in the context of writable storage: your App should be able to write to the file-system as well, Think: user uploads, CMS web based upgrades, online editing in themes and so on. So far so good for compatibility and usability. ### The Catch Of course there is a catch: Allowing your whole App to write on the storage, as we did and most of the other PaaS do, leads your App open to attacks from a certain vector: your very App itself. If there is a security vulnerability, not necessarily in your code, but in the framework or CMS part, which allows uploading `.php` files, an attacker can use this to inject mal-code into your App and then .. can do whatever he wants. On the lower level security side, we already took great care to truly and fully separated each App from another to limit any effect any compromised App has towards all the others. ### The Solution Recently our user [Francisco Azevedo](http://www.advertbrands.com/) pointed out that we could (and should) grant more control of the level of security our users have over their Apps. He wondered why there is no way to limit write access for Apps and suggested that Apps might even have no write access at all per default. We thought about this and created our new Write Protection feature. We think that this implementation brings best of both worlds together: By default write protection is off. This is important to assure compatibility and also most Apps start out in development. It is essential that new fortrabbit users get their stuff up and running easily, without obstacles. We think that Apps in development (mostly in the freemium plan) don't need write protection necessarily. Of course you can turn on (or off) write protection at any time in the web interface. When you scale your App to a production level plan and write protection is off, you will be presented with a very visible warning message that is a good idea to finally turn it on now. ### Our Learnings This issue touched us deeply. You can't imagine how much effort we put in designing the platforms infrastructure architecture. We think that it is the best thing we have ever done. Yet there was still this important detail that we haven't thought through enough. Our learning is that we should always be on the guard and question all of our moves as carefully as we could. Thanks again to Francisco for this very valuable feedback. It is a great honor for us to have such smart users who also really care so much. # The tyranny of inconsistent keyboard shortcuts Source: https://blog.fortrabbit.com/the-tyranny-of-inconsistent-keyboard-shortcuts Created: 2024-02-12 Author: Frank Lämmer > Insert a link in Slack, Notion, Linear, Obsidian and VS Code, and get five different shortcuts. A rant about relearning basic actions. This is specifically about my experience using: Linear, Notion, Slack, 1Password, Intercom, Google Docs, Obsidian and VS Code in parallel. It applies to standalone applications on my macOS system, but also to software in the browser. ## Examples - Insert a link - Slack: `⌘ + ⇧ + U` - Most others: `⌘ + K` - Show the sidebar - VSCode: `⌘ + B` - Notion: `⌘ + \` - Linear: `[` - Search - VS Code: `⌘ + P` - Notion: `⌘ + P` or `⇧ + ^ + ⌥ + ⌘ + K` - Linear: `/` - Slack: `⌘ + G` and `⌘ + F` - Intercom: `⌘ + P` - Command toolbar - VS Code: `⌘ + ⇧ + P` - Intercom: `⌘ + K` - Obsidian: `⌘ + P` - Inline code block - Slack: `⌘ + ⇧ + C` - Most others: `⌘ + E` - Copy the link to the current context - Notion: `⌘ + L` - Linear: `⌘ + ⇧ + .` - Slack: `L` but only if you clicked the menu already I am German, and certain characters like `[` and `]` are hard to reach on a German keyboard. So I have an English keyboard now and need to do a limbo to type an `Ü`. I can only imagine how hard it is for Dvorak users. Modern WYSIWYG editors have 'Markdown support', yet I often find myself struggling to escape a code block or changing a headline class. `⌘ + N`, `⌘ + C`, `⌘ + V` are set in stone. But even what the `ESC` key does varies a lot. I hit `⌘ + S` every 5 minutes in any document, it's part of my muscle memory. Now Linear will strike out my text for that. Without warning 1Password recently introduced a global (!) shortcut to open the mini window. Now when I try to indent code in VS Code, 1Password pops up ([Reddit](https://www.reddit.com/r/1Password/comments/wzmh9j/disable_global_keyboard_shortcuts_in_1password_8/)). Is locking-in users through custom shortcuts your business strategy? At least some programs let you tweak shortcuts. ## A modest proposal VS Code and other IDEs offer 'keymaps': sets of keyboard shortcuts that are compatible with other programs. Sublime user switching to VS Code? No problem, continue using your shortcuts. That's a good start. Imagine an operating system providing keymap settings. Or maybe that is happening in the browser. With that, a (web) application doesn't need to know where you are located, which keyboard layout you are using or what your preference is. It just needs to compute after receiving an event. This is a plea for standardization, advocating for a more harmonious keyboard shortcut landscape. Universal shortcuts: one command, any app, no config hassle. ## My background We are currently working on a browser based graphical interface (dashboard) for our [new hosting platform](https://new.fortrabbit.com). In addition to mouse navigation, I was keen on creating a system that can be controlled by keyboard in a fast and accessible way. The lack of available standards was the main reason we abandoned the project. As a small team, we can't put much effort into an island solution. I like standards. Browsers already offer native keyboard navigation. With the `TAB` you can cycle focus through active elements. Use `SPACE` to select things and arrow keys to travel through radio groups. There is accesskey ([MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey)) and [WebAIM](https://webaim.org/techniques/keyboard/accesskey) as well. But are they suited for modern requirements? I am not so sure. I will never learn VIM, but I can understand VIM users who don't want to learn something else. **EDIT**: I was pointed to existing software solutions. There are for sure browser extensions. For macOS there is a (free) App [customShortcuts by Houdah](https://www.houdah.com/customShortcuts/), which also is compatible with [KeyClu](https://github.com/Anze/KeyCluCask). # 3 ways to reset the Craft CMS control panel password Source: https://blog.fortrabbit.com/three-ways-to-reset-the-craft-cms-control-panel-password-without-email-access Created: 2024-10-17 07:16:31 Author: Piotr Pogorzelski Tags: webdev > Need to reset your Craft CMS admin password but email functionality isn't working? In some situations, you might find yourself needing to reset a Craft CMS admin password, but your server's email functionality isn't active. Under normal circumstances, you would reset your password by requesting a password reset email through the control panel login page, which sends a link to reset your password. However, if [sendmail](https://en.wikipedia.org/wiki/Sendmail), server's email functionality is inactive, this method won't work. This can happen due to various reasons such as website living in the environment without email setup, or security policies that disable email services. Disabling sendmail is a common security measure due to possible security exploits, such as email header injection, which can be used to manipulate email content or redirect messages to unintended recipients. Additionally, if sendmail was improperly configured, it could be exploited to send spam, launch phishing attacks, or relay unauthorized emails, potentially leading to the server being blacklisted. Here, we'll explore three methods to reset your admin password without relying on email server: using the Craft console command, updating the database directly, and using fake email service such as Mailtrap. ## Method 1: Using console commands If you have SSH access to your server, the simplest way to reset your Craft CMS admin password is through the [console commands](https://craftcms.com/docs/5.x/reference/cli.html) provided by Craft. This is the preferred method and should be your default approach. Follow these steps: 1. Log in to your server via SSH. 2. Navigate to your Craft CMS project directory. 3. If you don't remember the admin username, list all admin users with the following command: `php craft users/list-admins`. 4. Run the following command to reset the password: `php craft users/set-password `. Replace `` with the username of the admin account you want to reset the password for, and `` with the new password. This method is straightforward and secure, assuming you have SSH access to your server. ## Method 2: Using sandbox email server If you prefer to use the password reset functionality provided by Craft, you can connect your Craft CMS installation to an email inspection service that operates in sandbox mode. In sandbox mode, the service will store the emails instead of sending them, allowing you to inspect the emails and retrieve the password reset link. One such service is Mailtrap, which offers a free tier for a limited number of emails. Alternatively, you can use other services like [SendGrid](https://www.twilio.com/docs/sendgrid/for-developers/sending-email/sandbox-mode) in sandbox mode. To use Mailtrap, follow these steps: - Sign up for a free Mailtrap account at [Mailtrap](https://mailtrap.io/). - Set up a new inbox in Mailtrap and note the SMTP credentials provided (SMTP host, port, username, and password). - Configure Craft CMS to use Mailtrap for sending emails by updating your `config/app.php` with the following settings: ```php 'components' => [ 'mailer' => [ 'class' => craft\mail\Mailer::class, 'transport' => [ 'class' => \yii\swiftmailer\SmtpTransport::class, 'host' => 'smtp.mailtrap.io', 'username' => 'your_mailtrap_username', 'password' => 'your_mailtrap_password', 'port' => '2525', 'encryption' => 'tls', ], ], ], ``` - Request a password reset email through Craft CMS. - Check your Mailtrap inbox for the password reset email, open it, and follow the link to reset your password. This method allows you to use Craft's built-in password reset functionality without requiring a live email server. ## Method 3: Manual database update If for some reason SSH isn't working or isn't your preferred method, you can manually update the database to reset your password. Keep in mind that it is "hacky" method and should be avoided if you are able to use other password reset methods. Passwords in the database are stored in the hashed format, so you need to generate hashed string for password first, using a `bcrypt` hashing that Craft CMS uses. This can be done using Twig template that will access craft security service to generate hash for password string. This twig code can be placed in file `password.twig` in your `templates` directory. Thanks to the Craft template routing, it will be available at `yourproject/test` url, where `yourproject` is address of your website. The output of this template will be hashed string. ```twig {% set plainPassword = 'your_new_password' %} {% set hashedPassword = craft.app.security.generatePasswordHash(plainPassword) %} {{ hashedPassword }} ``` Now you can log in into your production server database manager such as phpMyAdmin. Navigate to the `users` table in your database and find the admin user whose password you want to reset. Edit the `password` field, replacing its value with the generated hash. Note that while phpMyAdmin has option to hash data that is entered, it does no support bcrypt, which is why we needed to hash it ourselves. Important: Make sure to avoid using this method of password generation on the live server, as it would expose your password generation template to the entire internet. Instead, you can do use local copy of the website, or even separate Craft install. Additionally, ensure that the file is removed afterward and not committed to the website's Git repository by mistake later. ## Related Craft CMS reading - [User account management with Craft CMS](/craft-cms-user-account-management) — the user system these recovery methods touch. - [Things to know about fast Craft CMS websites](/craft-performance-tuning-debugging) — performance tuning across the stack. - [Opinionated Craft CMS 4 upgrade guide](/opinionated-craft-4-upgrade-guide) — what to know before upgrading. _DISCLAIMER: fortrabbit has co-sponsored this blog post. It's cross published here. The original version can be found over at [craftsnippets.com](https://craftsnippets.com/articles/three-ways-to-reset-the-craft-cms-control-panel-password-without-email-access)_ --- - [Craft CMS guides](/guides/craft-cms) # TLS free launched Source: https://blog.fortrabbit.com/tls-free-launched Created: 2016-06-15 Author: Frank Lämmer Tags: changelog > Free SSL certificates for custom domains via Let's Encrypt are here now. **TL;DR** All custom domains with your fortrabbit (New) App can now also be served via `https://` with a valid certificate from Let's Encrypt unless a custom certificate is installed. Check out our [TLS help article](https://help.fortrabbit.com/tls) to learn more on implementation or continue here to read about what changes and a bit about the backgrounds. ![Browser Screenshot of TLS in action](/images/tls-free-screenshot.png) ## The changes ### TLS on fortrabbit so far **Piggyback TLS for the App URL**: Free TLS for testing: Your fortrabbit App comes with an App URL (your-app.frb.io). This first address can already be accessed by HTTPS with a valid certificate provided by us, so you can develop your App to be HTTPS-ready. **TLS custom**: Additionally you can book our TLS Component to bring your own custom certificate (from any CAs) and install it on the App for your custom domain. ### TLS on fortrabbit now **Piggyback TLS for the App URL**: Stays as it is of course, as you might want to test HTTPS without routing a domain. **TLS free**: Certificates from Let's Encrypt for every custom domain on your fortrabbit App are being issued, installed and renewed automatically. So you can use HTTPS on your own domains right away without configuration and for free. **TLS custom**: Also stays as it is, as there are many use cases for this as well (see below). ### When to use TLS free A quick and easy way to benefit from transport security for your App. Use it for small sites, hobby projects, during development for tinkering and for testing. No setup required, it's just there. ### When to use TLS custom The more sophisticated, advanced way to achieve transport security. The setup is a bit more complicated and you need to purchase the certificate on your own as well as the TLS Component from fortrabbit. Your own commercial certificates can deliver a higher level of trust and they also offer some advanced configurations that are not possible with the free version (eg wildcard). ## Some backgrounds ### About TLS TLS stands for Transport Layer Security and is the successor of SSL (Secure Sockets Layer). It's the cryptographic protocol that is used when you access a domain over a protected `https://` connection. HTTP happens on port 80, HTTPS on port 443. Back in the days only business critical applications, like banking or e-commerce needed encryption. But nowadays Google and others are promoting to use "HTTPS everywhere" (for more online security). ### About Certificate Authorities In order to communicate privately and encrypted, you need to know that your counterpart is who he claims to be. That's where certificate authorities (CAs) come into play: In essence, it's a chain of trust: they know somebody, who knows somebody, who knows somebody … who knows you. Pay a little money, send over a facsimile and they'll confirm that you are you. The more money you pay the more thoroughly they will check you out and the more your customers can trust that you are who you claim to be. Classical CAs are: Comodo, Thawte, DigiCert, GeoTrust, Symantec, GlobalSign and StartSSL … ### About Let's Encrypt [Let's Encrypt](https://letsencrypt.org/) is relatively new project aiming to bring certificates to everyone. It's a free, open and automated Certificate Authority. The service itself left beta in April this year. The Let's Encrypt setup is a bit different to classical CAs: the certificates only have a lifetime of ninety days. New certificates should be requested and installed automatically using a special client. Developers really love Let's Encrypt and it already has a [market share of 0.1%](https://w3techs.com/technologies/details/sc-letsencrypt/all/all). ### Benefits of the fortrabbit implementation You can install, configure and maintain such a client on your VPS yourself of course. But for fortrabbit clients it's part of the platform, just there for you to use. We take care of hosting and you of the coding. --- Ok, this here is way below the fold. I am sure nobody is reading any more. So here is: ## My opinion (not fully aligned with my colleagues) With this update we finally fulfill a frequent feature request. Traditional HTTPS is a hustle and means extra costs and DIY-lets-encrypt at least requires time, know how and responsibility. This update makes the fortrabbit even more attractive. ### Lowering entry barriers **This is what I really like about it**: HTTPS is often a business requirement. But setting up TLS - by it's nature - was a complicated process so far: Creating keys and certs locally, purchasing certs from (shady-looking) external providers, Uploading keys … We tried to make the process as easy as possible, but it was still a hustle. So from a very complicated setup to no setup required at all is a major improvement. From costs on the fortrabbit side and on the external providers side to no costs at all is also a very good deal. ### Increasing general web security **This is where I am bit sceptical**: There is [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication), which enables multiple certs per IP making hosting HTTPS much more efficient and more affordable - we introduced that in December 2015. There is HTTP/2 which is only supported by browsers when running over HTTPS. Google, Apple and others pushing for a wider [HTTPS](http://techcrunch.com/2016/06/14/apple-will-require-https-connections-for-ios-apps-by-the-end-of-2016/) [adaption](https://www.youtube.com/watch?v=cBhZ6S0PFCY) — Chrome (Canary) and Firefox now even display a red icon when for HTTP-only-websites. And we have Let's Encrypt solving the big authentication obstacle. On the other side, we have seen some serious security bugs in this space lately: [Heartbleed](https://en.wikipedia.org/wiki/Heartbleed), [Poodle](https://en.wikipedia.org/wiki/POODLE), [Drown](https://en.wikipedia.org/wiki/DROWN_attack) and now just recently the [Padding Oracle](https://en.wikipedia.org/wiki/Padding_oracle_attack). So, we are in the middle of a security arms race. Now as HTTPS is becoming a commodity, what will that mean for security? Will HTTPS be as safe as CD copy protection or as secure WIFI protected by WPS? ### Further readings Still don't have enough? Then you might also see my other rant article on the topic: [httpspeedy](/httpspeedy) with even more trade-offs. # Tools for PHP development — local dev site setup Source: https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup Created: 2020-07-30 Author: Jascha Silbermann Tags: webdev > What PHP development tools are available? What are the pros and cons of each tool? Not only does a local PHP development environment **speed up and simplify development**, when done correctly it also allows different team members to use the same environment on their respective machines. This reduces the amount of friction between team members and allows for smoother deployments. While the advantages of local PHP development are clear, the process of getting a dev site up and running **can be one of the least enjoyable parts of a PHP development** project. For WordPress, an integrated solution in the form of [Local by Flywheel](https://localwp.com/features/) exists. But for the generalized case of “PHP development” everybody seems to come up with their own solution. There are **many ways to set up a local PHP development environment**, and developers and designers alike are looking for ways to streamline their local development. Our discussion of the topic will revolve around three central questions: 1. [**What does a local PHP development environment consist of?**](#php-development-environment) What is a local PHP development environment? What software components and settings are required? 2. [**What should a local dev site setup look like?**](#local-dev-site-setup) What considerations should we make? What guidelines can we stick to? 3. [**What tools are available to set up a local PHP dev site?**](#php-development-tools) What are the pros and cons of each tool? What tool is best suited for different use cases? ## What a local PHP development environment consist of In essence, a local development environment comprises **everything needed to _run_ local dev sites**. This commonly includes software that needs to be installed and configured to work together in concert, such as a web server, database, and so forth. Note that a development environment may be specific to a language or ecosystem. As such, a developer **may need to set up multiple development environments** on their machine. Each development environment, in turn, may be used to run multiple dev sites. Let's look at all of the parts a local development environment consists of: 1. **Software stack** For most PHP projects, this will include a database and web server, in addition to PHP itself and the underlying operating system. To give an example, the venerable LAMP stack consists of **L**inux + **A**pache + **M**ySQL + **P**HP. 2. **Project codebase** This is the custom code that our actual app or website consists of. The codebase will normally be held in a Git repository. 3. **Environment configuration** While the codebase should be the same for production and local environments, there are a number of settings that will differ between environments. These include database credentials, site URLs, ports, and the like. By convention, these settings are excluded from version control and are instead held in so-called `.env` files. In production, the use of `.env` files is often discouraged for performance reasons. In this case, the values are instead directly made available by the environment. 4. **Development tools, scripts, and configuration** For development, we will normally use a number of tools, such as Git, Composer, Node, Yarn, Gulp, and so forth. Some of these may only be needed for local development, others may also reside on the server. Additionally, we often end up writing custom “glue” code to tie things together. This includes shell scripts, Git hooks, as well as configuration files. Generally, these code files should be under version control, but may be in a separate repository. 5. **Local host name configuration** Whereas the preceding points pertain to both local and remote environments, this point and the following apply only to local development. When running dev sites locally, we need to provide a way of mapping local host names back to our sites. To give an example, when accessing a local dev URL such as `http://devsite.local` in the browser, how is this request passed on to the site we're developing? The canonical way to set this up is to add custom entries in the `/etc/hosts` file. Alternatively, a tool such as DnsMasq may be used to automatically configure local host names for our projects. 6. **Virtualization / containerization tools + configuration** Virtualization / containerization is the method of choice for local development, and so we will need the appropriate software installed on our local machine. This includes tools such as Vagrant or Lando. These tools are normally controlled via a configuration file (Vagrantfile, Landofile, etc.), which should be under version control. 7. **Shared folders** When running a virtualized development environment, we often find the need to share files between our local machine and the virtual machine / container. For example, we can share our local project codebase to the virtualized environment. On our local machine, the codebase is just a bunch of files. But inside the virtualized environment, where we can run the code, our project comes alive. The standard way to accomplish this is to set up a network-shared folder. Everything inside this folder on the local machine will be accessible inside the virtualized environment. As should be clear by now, a local development environment consists of quite a few interrelated parts. As such, there are many ways to set things up, with ample room for us to end up with suboptimal results. While development tools can help with some of the setup, the **precise balance of components is specific to each development workflow**. We therefore look for guidelines to find a good solution. ## What our local dev site setup should look like ![local-php-dev--7515248418_831c15e4d7_o](/images/local-php-dev--7515248418_831c15e4d7_o.jpg) Photo of an old Apple computer by Steve Jurvetson via Flickr In essence, we want to be able to run multiple dev sites in parallel. Each dev site may require different dependencies and configuration. Ideally, we want to have a **standardized approach that we can rely on for every dev site** we want to set up. Here are some guidelines for the sort of system we want to end up with: 1. Set up a dedicated local development environment. This means we're able to **run our web-based software and access its services on our own machine**. Without this, we would need to push code to the server to test any code changes. Not being able to test code locally seriously slows down development. Furthermore, if we need to push before testing we'll likely also end up polluting our repository with superfluous commits in the process. 2. **Isolate the development environment** from our physical machine's operating system. We want to protect our system from becoming corrupted when updating or adding a dev site. Likewise, we need to protect our existing dev sites from becoming corrupted when changing our system. 3. **Isolate each dev site**. We want to avoid version conflicts and interference between dev sites. Adding a new site should not break existing sites; updating dependencies for one dev site should not cause a version conflict in another one. 4. **Ensure ability to deploy to production and staging**. We need to be able to push code and configuration from our local development environment to the remote environments. How to set this up depends, but generally there will be some form of Git deployment. Keep in mind that some files will likely be outside of version control. For those, we may need to employ custom sync scripts. 5. **Keep the local development environment as close to the production environment** as possible. We need to be able to match the dependencies and services in the production environment to our local development environment. This also means we need to be able to adjust the locally installed software when changes to the server are made. 6. Make sure we **know how to recreate our dev sites**. On one hand, this is crucial in the case of a catastrophic failure. On the other hand, whenever we need to onboard a new team member it's nice to be able to get them set up without hassles. ## Four general ways to set up a local dev site In principle, all four ways can be used to run local dev sites. However, in practice **most use cases are best served using a virtual machine- or container-based approach**. 1. **Set up all of the stack components on our local machine:** Examples: **Custom LAMP-stack**, **Valet** ✓ Highest possible performance of any solution ⨉ No isolation of dev environment and local machine ⨉ No code-based configuration layer ⨉ Lack of dev site isolation 2. **Use a pre-packaged stack with GUI:** Examples: **XAMPP** / **MAMP** / **WAMP** ✓ Easy setup ✓ GUI ⨉ No code-based configuration layer ⨉ Lack of dev site isolation 3. **Install all the stack components inside a virtual machine (VM):** Examples: **Vagrant**, **Homestead** ✓ Comfortable ✓ Powerful ✓ Dev site isolation via separate virtual machines ⨉ Resource-hungry ⨉ Lots of disk space needed for dev site isolation 4. **Distribute the stack components across multiple containers**: Examples: **Docker**, **Lando**, **DDEV** ✓ High performance ✓ Low disk space requirement per site ✓ Dev site isolation ⨉ Performance issues if not running Linux ⨉ Known issues with certain tools and techniques ## Tools for running a local PHP dev site We'll look at the pros and cons of each tool. Be aware that **some of these tools cannot be used in parallel.** 1. [**Vagrant**](#vagrant) (VM) 2. [**Homestead**](#homestead) (VM) 3. [**Valet**](#valet) (System) 4. [**Docker**](#docker) (Container) 5. [**DDEV**](#ddev) (Container) 6. [**Lando**](#lando) (Container) ### Vagrant ![local-php-dev--vagrant](/images/local-php-dev--vagrant.gif) Vagrant is a popular tool for **configuring and running a local development environment inside a virtual machine**. To accomplish this, Vagrant works with different virtual machine providers, such as VirtualBox, VMware, etc. To set up the development environment, Vagrant uses a provisioning tool, with Chef and Puppet being major examples. To tie everything together, Vagrant employs a Ruby script called a “Vagrantfile”. In theory, the **Vagrantfile contains all of the information needed to replicate a dev environment** from a given box. However, in practice one may end up with a minimal Vagrantfile and the actual configuration pushed off to the provisioning tool's configuration. Development with Vagrant starts with a “box”, which is a pre-packaged environment geared towards a specific use case. There are **many [publicly available boxes](http://www.vagrantbox.es/) to choose from**; these can range from a bare Linux / Unix operating system to a fully-configured dev environment. For PHP development, one can choose from a range of specialized boxes. These commonly include pre-installed software such as: - Apache and / or Nginx - MySQL or MariaDB - PHP 7.x - PHP-fpm - Git - Composer - Xdebug Besides the software components, a box normally comes with **network interfaces and ports set up** and ready for use. This should allow one to get started, although some tinkering may be required to get everything configured for the specific use case. Fortunately, Vagrant makes the **process of configuring the development environment easy**: configuration is stored in simple text files, which should be held under version control. After a change to the configuration is made, one re-provisions the machine. Should something go wrong in the process, it is straightforward to tear down the machine and start over. Configuring a **Vagrant box affords a lot of control**. However, for most PHP development use cases it's probably a better idea to start with Homestead. Website: [vagrantup.com](https://www.vagrantup.com/) Supported operating systems: Linux, macOS, Windows ### Laravel Homestead ![local-php-dev--homestead](/images/local-php-dev--homestead.gif) Homestead is a **Vagrant box provided by the Laravel project**. The contents of the box are geared towards PHP development: > “Laravel Homestead is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. No more worrying about messing up your operating system!” Homestead comes packed with lots of cool features: one can run multiple dev sites inside a single Homestead machine, each with its own PHP version and SSL setup. There are **dedicated commands for common operations** such backing up and restoring databases. Homestead also supports multiple web servers and allows one to gracefully switch between them. Instead of Vagrant's traditional Vagrantfile, Homestead uses a `Homestead.yaml` file for configuration. This **file contains all of the configuration for our project** and can shared amongst a team to set up identical development environments. Be aware that a Homestead instance **may results in a large virtual machine file**. It's not unusual for this file to take up 5-15 GB of storage on the local disk. To achieve true dev site isolation, we might have to spin up multiple instances of Homestead. If our local machine only has a small SSD, this can present a serious disadvantage. Website: [laravel.com/docs/7.x/homestead](https://laravel.com/docs/7.x/homestead) Supported operating systems: Linux, macOS, Windows ### Laravel Valet ![local-php-dev--valet](/images/local-php-dev--valet.gif) Valet is yet another technology by the Laravel project. However, it is not a Vagrant box and follows a radically different approach to local development: instead of setting up a development environment inside a virtual machine, Valet is **installed directly on top of the physical machine's operating system**. This affords high performance, but also brings several serious downsides: - Valet only works on specific machines and requires changes to the local system: > “Valet only supports Mac, and requires you to install PHP and a database server directly onto your local machine.” - Valet relies on multiple services running on the local machine: > “Laravel Valet configures your Mac to always run Nginx in the background when your machine starts. Then, using DnsMasq, Valet proxies all requests on the \*.test domain to point to sites installed on your local machine.” It's not hard to imagine that things can go seriously wrong with this kind of setup: any changes we make to our operating system or the Valet dependencies carries a **risk of breaking our development environment**. Since we're not inside a virtual machine, we cannot just tear-down and re-provision. Good luck fixing Valet if it breaks. That being said, when going with Valet one should make sure to **keep up-to-date full system backups**. Then just restore to a working version if the system breaks in any way. In conclusion, Valet may be a good choice for a developer working within a single, specific ecosystem. The makers of Valet advise that: > “Valet isn't a complete replacement for Vagrant or Homestead, but provides a great alternative if you want flexible basics, prefer extreme speed, or are working on a machine with a limited amount of RAM.” Website: [laravel.com/docs/7.x/valet](https://laravel.com/docs/7.x/valet) Supported operating systems: macOS only ### Docker ![local-php-dev--docker](/images/local-php-dev--docker.gif) So far we've discussed virtual machine-oriented approaches. These provide great compartmentalization of our development environment, but can take up a lot of disk space and usually incur a noticeable performance hit. More modern solutions **ditch the virtual machine and employ sets of lightweight containers** instead. Containers provide an abstraction on top of the native operating system kernel, which yields a significant performance boost. Each stack component is installed in its own container, which makes it easy to, for example, have multiple versions of a database running side-by-side. In theory, containers are the ideal solution, as they afford **perfect separation of development environments** while keeping performance high and disk usage low. However, in practice there are known Docker-specific issues: - Docker Desktop on Mac and Windows uses a virtual machine, negating some of the performance benefits. - Xdebug and symlinked repositories can be problematic with Docker. Furthermore, setting up a development environment with Docker is technically challenging. Unless you're super pro and know exactly what you're doing, you most likely don't want to go with pure Docker. It's **probably a better idea to use an abstraction layer**, such as Lando or DDEV, to set up your container-based local PHP development environment. Website: [docker.com](https://www.docker.com/) Supported operating systems: Linux, macOS, Windows ### Lando ![local-php-dev--lando](/images/local-php-dev--lando.gif) Lando is a powerful dev tool based on Docker. The basic idea is to allow us to **enjoy the benefits of Docker containers, without the headache** of having to configure them. Development with Lando begins with a “recipe”. **A recipe is to Lando sort of what a box is to Vagrant**: a pre-defined set of technologies that are meant to be used together to run dev sites. > “Recipes are Lando's highest level abstraction and they contain common combinations of routing, services, and tooling” The range of **Lando recipes encompasses different stacks**, such as LAMP, LEMP, and MEAN. One can also find specialized recipes for popular content management systems and web application frameworks. Whether looking to start a project using Drupal, WordPress, or Laravel, Lando has got you covered. For general PHP development, we can start out with a LAMP recipe. Once we initialize our Lando project, a YAML config file is created for us. This so-called **“Landofile” contains all the configuration for our project**. Here, we can define our PHP version, ports and other network settings, environment variables, and the like. Generally, Lando strives to provide sane defaults via its recipes and offers mechanisms to allow us to override these defaults. All in all, Lando appears to be a well-thought-out and mature solution. Besides easing the pains of local development, Lando strives to reduce the distance between the local dev environment and remote staging / production environments. Furthermore, Lando aims to allow an entire dev environment to be reproduced from configuration files alone. These properties make Lando an **attractive choice for team-driven, professional development**. One word of caution: Lando for macOS and Windows ships with its own version of Docker Desktop, which **can cause problems if you already have Docker installed on your system**. Lando also has pretty [hefty hardware requirements](https://docs.lando.dev/basics/installation.html#preferred), which may present a serious barrier for some developers. Website: [lando.dev](https://lando.dev/) Supported operating systems: Linux, macOS, Windows ### DDEV ![local-php-dev--ddev](/images/local-php-dev--ddev.gif) DDEV is another dev tool based on Docker. The basic idea is the same as for Lando: provide a **comfortable configuration layer and sane defaults on top of Docker**. Instead of starting from scratch, we hit the ground running. Unlike Lando, DDEV is **exclusively geared towards PHP development**. Although it lacks a concept of “recipes”, DDEV does provide specialized configurations for commonly-used PHP content management systems and frameworks. At the time of writing, DDEV comes with configuration support for the following systems: - WordPress - Drupal 6/7/8/9 - TYPO3 - Magento 1/2 - Laravel The singular focus on PHP development simplifies things, as it allows the makers of DDEV to make more opinionated choices. Out of the box, DDEV includes useful tools, such as Xdebug, Ngrok, and MailHog. All in all, **DDEV feels more light-weight than Lando and may presently be the quickest solution** to getting a PHP dev site up and running. Website: [ddev.com](https://www.ddev.com/) Supported operating systems: Linux, macOS, Windows Please also see our [follow up post on how to set up DDEV for Craft CMS](/local-craft-dev-site-ddev-development-tool) in 15 minutes. ## In conclusion, what tool should we use to run our local dev sites? The tools for setting up a local development environment all aim to solve a similar problem, but balance the tradeoffs differently. As such, there really is **no “one size fits all” perfect solution**. It is safe to say that each solution comes with its own advantages and disadvantages. To get a better picture, we should expand our view beyond purely technical factors, and **include each solution's ecosystem in our consideration**: can we rely on up-to-date documentation and ongoing development? Is it easy to find bug reports, answered StackOverflow questions, and blog posts on specific topics? Furthermore, to find the right solution for our needs, **we need to ask ourself: what kind of development are we doing**? Are we exclusively building PHP sites, or using other languages as well? Within our language of choice, are we working mainly within a single, specific ecosystem, or are we developing using different frameworks and systems? While it is difficult to give detailed recommendations, here's a **condensed rundown of the technologies discussed, along with their strongest use case**: ### For most use cases go with… - [**Homestead**](#homestead), if you're fine with using a virtual machine. Homestead offers a great ecosystem, so it's easy to find guides for setting up different PHP-based projects. Since Homestead runs on top of Vagrant, you can just add more boxes for development in other languages if needed. Keep in mind that each box eats up multiple gigabytes of disk space. - [**DDEV**](#ddev), if you're only going to develop using PHP and want to get your site up and running as quickly as possible. This is an especially good choice if you're running Linux, as you'll get the full Docker performance benefit. ### If you have special requirements, consider… - [**Vagrant**](#vagrant), if you need customizability above all else and are fine with using a virtual machine. - [**Valet**](#valet), if you're looking to build a dedicated, single-purpose dev machine. This is the laptop you pick up every day for work. You don't use it to store personal documents, nor to manage a portfolio of diverse projects. Instead, you set this machine up for a single, long-running project, or to work on multiple projects within a single ecosystem. - [**Docker**](#docker), if you need customizability above all else, or need to faithfully re-create a containerized production environment. For experienced users only. - [**Lando**](#lando), for larger teams and professional deployments. Make sure your hardware is beefy enough for Lando to do its job. Unlike DDEV, Lando supports multiple languages via its recipes. - **XAMPP** / **MAMP** / **WAMP**, for learning and experimentation. These are not a great choice for serious development, due to the lack of site isolation. ### Dev tool feature overview and comparison Use this table to get a quick overview of the relative strengths and weaknesses of each tool. Read the symbols as follows: - `✓` Outstanding - `⌀` Average - `✗` Lacking | Dev tool | Site isolation | Ease of use | Customization control | Low hardware requirements | High performance | | :------------ | :------------: | :---------: | :-------------------: | :-----------------------: | :--------------: | | **Vagrant** | ⌀ | ✗ | ✓ | ⌀ | ✗ | | **Homestead** | ⌀ | ⌀ | ⌀ | ⌀ | ✗ | | **Valet** | ✗ | ⌀ | ⌀ | ✓ | ✓ | | **Docker** | ✓ | ✗ | ✓ | ⌀ | ⌀ | | **Lando** | ✓ | ⌀ | ⌀ | ✗ | ⌀ | | **DDEV** | ✓ | ⌀ | ⌀ | ⌀ | ⌀ | | **XAMPP** | ✗ | ✓ | ✗ | ⌀ | ✗ | # Under the hood updates Source: https://blog.fortrabbit.com/under-the-hood-updates-2019-06 Created: 2019-05-28 Author: Frank Lämmer Tags: changelog > A large internal platform update focused on stability, security and groundwork, with the timing and downtime to expect per app. ## Run down The updates will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 30 minutes, we aim for a few minutes. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect a maximum downtime of around 6 hours. Also the updates will run sequentially, so the individual per App down-time likely will be less. Please keep an eye on our (new) [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Dates We are going to run those updates first in US and a few days later in EU: ### US maintenance **Monday, 3rd of June 2019** starts at 08:00 UTC 04:00 AM in NYC 01:00 AM in SF 10:00 AM in Berlin ### EU maintenance **Sunday, 9th of June 2019** starts at 10:00 UTC 12:00 PM in Berlin ## Client facing changes Alongside some new minor patch versions will be installed, as well. Here is the complete list of client facing changes: ### Changed PHP versions - php (5.6) > dropped already - php (7.0) > dropped already - php (7.1.16) > 7.1.29 *← caution EOL is EOY !* - php (7.2.14) > 7.2.18 - php (7.3.1) > 7.3.5 ### Updated extensions - apcu (5.1.16) > 5.1.17 - [changelog](https://pecl.php.net/package-changelog.php?package=ev) - igbinary (2.0.8) > 3.0.1 - [changelog](https://pecl.php.net/package-changelog.php?package=igbinary) - imagick (3.4.3) > 3.4.4 - [changelog](https://pecl.php.net/package-changelog.php?package=imagick) - libsodium (1.0.6) > 1.0.7 - [changelog](https://pecl.php.net/package-changelog.php?package=libsodium) *— (dropped in 7.2 and 7.3) See below as well!* - phalcon (3.4.2) > 3.4.3 - [release notes](https://github.com/phalcon/cphalcon/releases) - redis (4.2.0) > 4.3.0 - [changelog](https://pecl.php.net/package-changelog.php?package=redis) - blackfire php probe (1.24.3) > 1.26.0 - [release notes](https://packages.blackfire.io/binaries/blackfire-agent/1.26.0/CHANGELOG) - blackfire agent (1.22.1) > 1.26.0 - [release notes](https://packages.blackfire.io/binaries/blackfire-agent/1.26.0/CHANGELOG) - newrelic php probe (8.5.0.235) > 8.6.0.238 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) - newrelic agent (8.5.0.235) > 8.6.0.238 - [release notes](https://docs.newrelic.com/docs/release-notes/agent-release-notes/php-release-notes) ### Added compile options - password-argon2 support added in PHP 7.2 and 7.3 - sodium support added in PHP 7.2 and 7.3 ### Updated libraries - cURL 7.35.0 > 7.58.0 - FreeType library 2.5.2 > 2.8.1 - used by `gd` - libPNG library 1.2.50 > 1.6.34 - used by `gd` - geoip library 1006000 > 1006012 - GMP library 5.1.3 > 6.1.2 - GPGme library 1.4.3 > 1.10.0 - used by `gnupg` - iconv library 2.19 -> 2.27 - Imagick library 7.0.8-25 > 7.0.8-46 - ICU library (libicu) 52.1 > 60.2 - used by `intl` - OpenLDAP library 20431 > 20445 - mbstring oniguruma library 5.9.1 > 6.7.0 - mongodb libraries (libbson, libmongoc) 1.8.2 > 1.13.0 - OpenSSL library 1.0.1f > 1.1.0g - PostgreSQL library (libpq) 9.3.24 > 10.8 - SQLite library 3.8.2 > 3.22.0 - Readline library 6.3 > 7.0 - Sodium library (libsodium) 1.0.12 > 1.0.16 - SQLite3 library 3.8.2 > 3.22.0 - SSH2 library (libssh2) 1.4.3 > 1.8.0 - Tidy library (libtidy) "25 March 2009" > 5.2.0 - XML library (libxml) 2.9.1 > 2.9.4 - XSL library (libxslt) 1.1.28 > 1.1.29 - YAML library (libyaml) 0.1.4 > 0.1.7 - ZLib library 1.2.8 -> 1.2.11 ### Updated services - `httpd` Apache (2.4.27) > 2.4.29 - `haproxy` Routing (1.8.9) > 1.9.8 ### Updated command line tools - `composer` - automatically kept up to date - `convert` ImageMagick (7.0.8-25) > 7.0.8-47 - [changelog](https://imagemagick.org/script/changelog.php) - `curl` (7.35.0) > 7.58.0 - `mysql` (14.14 dist 5.5.62) > 5.7.26 - `nano` (2.2.6) > 2.9.3 - `openssl` (1.0.1f) > 1.0.1g - `rsync` (3.1.0) > 3.1.2 - `tar` (1.27.1) > 1.29 - `vim` (7.4) > 8.0.1453 - `wp-cli` - automatically kept up to date ### Dropped command line tools - `drush` ### libsodium With the inclusion of sodium in core PHP 7.2 the name-spacing was dropped. In other words, the extension is not available any more, but included with the PHP core. We see that very few clients are using it. We will contact those affected individually. We keep the old extension for PHP 7.1, so for now, you can still switch back the PHP version in the Dashboard, or you can also use this polyfill: [https://github.com/mollie/polyfill-libsodium](https://github.com/mollie/polyfill-libsodium). # Universal App pricing V2 is here Source: https://blog.fortrabbit.com/universal-pricing-v2 Created: 2017-05-11 Author: Frank Lämmer Tags: chronicles, changelog > Universal App plans get reworked five months after launch: the entry plan goes, the middle plan takes its price, a top plan arrives. 1. The old entry level plan is going away. 2. The old middle plan is becoming the new entry plan — same specs, lower price. 3. A new powerful top plan is introduced. ### Specs & prices comparison table | ↓ Spec / Plan → | Light-V1 | Light | Basic-V1 | Standard | Plus-V1 | Plus | | ------------------- | -------- | -------- | -------- | -------- | ------- | ------- | | PHP memory | 128 MB | 128 MB | 128 MB | 256 MB | 128 MB | 512 MB | | PHP processes | 2 | 2 | 2 | 4 | 2 | 8 | | Web storage | 512 MB | 1 GB | 1 GB | 5 GB | 5 GB | 10 GB | | MySQL storage | 128 MB | 256 MB | 256 MB | 512 MB | 512 MB | 1 GB | | Backups | no | no | no | yes | yes | yes | | Crons | no | no | no | yes | yes | yes | | App collaboration | no | yes | yes | yes | yes | yes | | Performance metrics | no | yes | yes | yes | yes | yes | | Automatic HTTPS | no | yes | yes | yes | yes | yes | | Custom HTTPS | no | yes | no | yes | yes | yes | | Monthly price ($/€) | 3 | 5 | 6 | 15 | 12 | 30 | ### Why we are doing this The Professional Stack is designed for modern web applications, this mostly means Laravel apps or modern high traffic websites. The Universal Stack with more backwards compatibility has a wider range of applications. So we are seeing more classical legacy content driven websites, mostly CMS-based. Especially Craft-CMS is raising. And those software-systems sometimes need a little more horse-power to behave well. ### Existing plans don't change — it's opt-in If you have existing Apps: Don't worry! **Your current plans will not change.** You can scale up your App from your current V1 plan to a V2 plan. Any new Apps booked from now on need to be on the new V2-Pricing. ### The middle plan is now called Standard We are also changing a wording: We think that "Standard" is a better than "Basic" when is comes to the name for the plan in the middle, the plan we do recommend for most common use cases. ### More details Yes, this is a professionalisation of the Universal Stack. We are re-introducing the PHP processes here, an important metric that describes the number of maximum concurrent requests. More resources even for low/mid traffic sites with multiple (Ajax) requests per visit make a huge difference. And there are bigger PHP memory options available now, to support intensive tasks like image transformations without running into trouble. This is also a step back from features to hardware specs. For the sake of clarity we have skipped the distinctive features: Automatic HTTPS, Performance metrics and App collaboration, which are now always included. **Are we doing the right thing?** We are very curious what you think. # Universal Stack changelog Source: https://blog.fortrabbit.com/universal-stack-changelog Created: 2016-12-20 Author: Frank Lämmer Tags: changelog > Every change that came with the Universal Stack release, including New Apps being renamed to Professional Apps. No action required. ## New Apps > Professional Stack — WORDING Your "**New Apps**" are now called "**Professional Apps**". That's it. Everything else stays the same. We are fully committed to further support and develop the Professional Stack. ## Universal Stack — NEW With each App you create you can choose between the two stacks: **Universal** or **Professional**. The Universal is for smaller legacy projects, the Professional Stack for bigger, more ambitious ones. - [Read the announcement](/universal-stack-launched) - [Compare the stacks](https://help.fortrabbit.com/stacks) - [See the Universal Stack pricing](https://www.fortrabbit.com/pricing) - [Check out the Universal Stack specs](https://www.fortrabbit.com/old-platform/specs-uni) ### Backups — NEW for Universal Apps only The large Universal plan comes with a new Backups feature. We hope you like daily off-site encrypted backups with a 14 days retention span. We plan to offer backups for the MySQL Component of the Professional Stack as well. ![New Backups dialouge](/images/backups-preview.gif) - [Read the backups help page](https://help.fortrabbit.com/backups) ### MySQL 5.7 — NEW for Universal Apps only Universal Apps are coming with the **latest MySQL 5.7** version. We are evaluating to offer MySQL 5.7 for Professional Stack Apps as well. ### Full SSH & SFTP support — NEW for Universal Apps only One aspect of our Professional Stack Apps is ephemeral storage, which allows those Apps to scale horizontally to large degrees. The Universal Stack Apps are featuring persistent storage, which allows support for **direct SSH and SFTP access**: - [Read the SSH help page](https://help.fortrabbit.com/ssh-uni) - [Read the SFTP help page](https://help.fortrabbit.com/sftp-uni) ## Company plans — NEW The new Company plans are combining support and collaboration features. The "Developer" role is now called "**App Collaborator**" and is available for all Professional Apps and most Universal Apps. Company collaboration with "Admins" and "Owners" can be booked in various sizes: - [Read about the new collaboration in the help](https://help.fortrabbit.com/collaboration) Already booked support plans are automatically converted to Company plans with the same feature set. All existing collaboration configurations are untouched and can be used indefinitely for free. To be sure: Existing collaboration setups are completely untouched. No worries. Support literally has many faces. For us it's: A signal to learn about our customers, a sales channel and a great part of our work days. The support chat is open to everyone, but users with a Company plan have higher priority in the loop. ## Help pages — UPDATE The official fortrabbit documentation has been re-factored and re-edited. It now fully details the two stacks. Install guides for both stacks are available: - [See all the commits](https://github.com/fortrabbit/help/commits/master) - [See the new list of all articles, including deprecated ones](https://help.fortrabbit.com/all-articles) ## Improved design — UPDATE On our quest to improve ease of use, the look and feel of our web properties [www](https://www.fortrabbit.com), [blog](https://blog.fortrabbit.com), [help](https://help.fortrabbit.com) and of course [Dashboard](https://dashboard.fortrabbit.com) got a face-lift. We hope you like the new look while still feeling at home. The new styles ate featuring more visual hierarchy, clearer states. It's lighter, faster, uses less break points and there is less stuff to be loaded. ## Legal docs — CHANGE We did some tiny minor changes to our legal docs to reflect the new wordings and the aspect that canceling the service by letter is not secure. - [Diff the commits on GitHub](https://github.com/fortrabbit/legal/commits/master) ## App Secrets are becoming more optional — CHANGE OK. We got it: App Secrets are not a standard way of storing sensitive access details and are more cumbersome to work with than ENV vars. So we bow to the majority and have now improved support for ENV vars. This means that we will use ENV vars in all our documentation from now on and will migrate old documentation over time to use ENV vars as well. In addition, when creating any new App the software chooser, in which you choose framework or CMS, we will use ENV vars instead of App Secrets. Still, App Secrets for existing Apps are completely untouched and will be available for newly created Apps as well - they just became optional. - [See the new help article](https://help.fortrabbit.com/env-vars) ## Collaboration information changes — UPDATE For extra security through transparency, we are going to send more infos via mail on collaboration changes like demoting, promoting and leaving a Company. ## Unified HTTPS handling — UPDATE / WORDING It's true, everybody is still talking about SSL, but SSL is not in use any more. It's TLS now. But TLS is still not so well known. So we ditched all that and now refer to it as HTTPS, which is an acronym hopefully everybody will have heard of. - [See the new help article](https://help.fortrabbit.com/https) ## Better root path handling — UPDATE In the Dashboard, the root path (aka web root or document root) setting of your App can now also be obtained from the App overview directly. We also added an overview to show which domains are routed where. ![New Root path dialouge](/images/root-path-new.gif) ## Separation of "Performance Metrics" & "Usage Metrics"— CHANGE Performance Metrics are data visualizations which give you insights into the "speed" of your App. In turn they help you to optimize and evaluate performance changes after code deployments. Performance Metrics are available for all Professional Apps and most Universal Stack Apps. Usage Metrics, on the other hand, are just simple snapshots of current usage of resources of the App — for example: see how much MySQL storage your App is currently using. Those are always available. The two kind of metrics are now separated from each other. ![New Usage metric box](/images/usage-metric-inline.png) ## "Page views" instead of "PHP requests" — WORDING "PHP requests" is a core performance metric that shows many PHP executions your App handles: A PHP request is a single execution of a PHP script. Viewing one web page can result in multiple PHP requests, in rare cases. Usually that is not the case and "Page views" are much better known and understood. Hence we are changing the wording from "PHP request" to "Page view" to make the service offering more transparent and more comparable. We also replaced "All requests" which included all PHP requests + and all non-PHP requests for static assets (JS, IMG …). From now on you have "Static requests" in the Performance Metrics section of your App, which only contains non-PHP requests. We think that makes some more sense and is easier to understand. ## App alerts — COMING SOON This feature did not make it in the launch but will soon follow: As requested by many users, we will make service limit alerts available, which will send out mails to the App Owners if any resource is near exhaustion. This allows you to become aware of bottlenecks before they occur and allow you to scale in time. ## Longer trial time — UPDATE Some PHPeople complained that the App trial time is too short. Ok, it's longer now. And you can ask us to extend the trial a little after you have created it. ## Old App early bird universal migration bonus — FEATURE Still using Old Apps? You can migrate them easily to the Universal Stack. The owners of the first 100 moved Apps will get a discount of 20 €/$ on their next bill, please ping us in the support when you are about to move, we are also happy to give you support, if you require any. - [Migrating an Old App to an Universal App help page](https://help.fortrabbit.com/migrate-old-to-uni) ## Final End of Life date for Old Apps — UPDATE This huge platform update also marks the end of our first generation of Apps: Old Apps. We hereby inform you that the so called Old Apps will should be migrated by the **end of March 2017**. So don't worry, there is still time. And don't worry, we will also mail affected clients with more infos soon. We take this transition serious. --- You came a long way fellow scroller and we haven't bothered you with any christmas talk at all. # Universal Stack launched Source: https://blog.fortrabbit.com/universal-stack-launched Created: 2016-12-20 Author: Frank Lämmer Tags: changelog > Optimized for CMS driven websites - made for your needs: Backups, Git, SFTP, HTTPS & team collaboration. In [August we have revealed](/sneak-peek) that we are working on a new general purpose "hobby stack" to better support small projects and legacy PHP websites. Now, after months of intensive work and testing, we proudly release it. fortrabbit is available in two flavors now — one hosting platform for all the projects you are building — from website to web application, from xxs to XXXL, side by side. More PHPower for more PHPeople. With each App you'll create you can choose: ## 1. Professional Stack The Professional Stack — formerly known as New App — is made for state-of-the-art PHP development. It is a scalable high performance hosting solution for business critical web applications. The flexible structure is based on components which are individually scalable, vertical and horizontal. The Professional Stack is strictly based on modern web app design paradigms and thus made for sophisticated developers. ## 2. Universal Stack — NEW The Universal Stack is general purpose PHP cloud hosting. It mixes the best properties of traditional hosting: It's affordable as shared hosting, powerful as VPS hosting and carefree as managed hosting, plus it features some of the modern cloud hosting standards (Git, Composer …) you don't want to miss any more. It's made for small web applications and websites. Beginners and experienced developers can make use of it alike. ### Plans & pricing There are just three simple straight forward bundled App plans. All are great. The higher plans come with more MySQL database space and more web space and additional features like HTTPS for custom domains via Let's Encrypt, App collaboration and Cron jobs. * [See the Universal Stack pricing](https://fortrabbit.com/pricing) ### Included backups The highest plan comes with our brand new backup solution: fully automated web storage & MySQL backups, encrypted, offsite. * [Read the backups help page](https://help.fortrabbit.com/backups) ## Experience it yourself * [Sign up](https://dashboard.fortrabbit.com/signup) or [log in](https://dashboard.fortrabbit.com/login) to test drive a free trial App ## Digg deeper * [See the platform changelog](/universal-stack-changelog) including all infos for existing clients * [Learn more about the stacks](https://help.fortrabbit.com/stacks) # Patch updates ahead Source: https://blog.fortrabbit.com/updates-ahead-2019-10 Created: 2019-10-16 Author: Frank Lämmer Tags: changelog > A patch update for all supported PHP versions rolls out app by app, with up to ten minutes of downtime for web delivery. ## Run down The updates will affect all Apps (Uni and Pro). The expected downtime for App web delivery is up to 10 minutes, we aim for less. We will run the updates sequentially, App after App. Pro Apps on production plans are planned to have near-to-zero downtime. For the deployment services (Git, SSH and SFTP) we expect only a short downtime of a few minutes. Please keep an eye on our [status page](https://status.fortrabbit.com) where we are going to post intermediate updates. ## Maintenance date and time We are going to run those updates first in batches by region: ### US maintenance **Monday, 21th of October 2019** starts at 08:00 UTC 04:00 AM in NYC 01:00 AM in SF 10:00 AM in Berlin ### EU maintenance **Tuesday, 22th of October 2019** starts at 17:00 UTC 07:00 PM in Berlin The total maintenance window will be set for 7 hours. We aim for less. ## Client facing changes Here is the complete list of client facing changes: ### Changed PHP versions - PHP73 (7.3.8) > 7.3.10 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_3) - PHP72 (7.2.21) > 7.2.23 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_2) - PHP71 (7.1.31) > 7.1.32 - [changelog](https://www.php.net/ChangeLog-7.php#PHP_7_1) Caution: PHP 7.1 will reach its official end of life on 1 Dec 2018. We will still support it for a bit longer on our platform, but you should upgrade to 7.2 or 7.3 as soon as possible. [Read more about PHP's officially supported versions.](https://www.php.net/supported-versions.php) ### Updated extensions - ssh2 (1.1.2-79371d) > 1.2 - [changelog](https://pecl.php.net/package-changelog.php?package=ssh2) - blackfire php probe (1.27.0) > 1.27.1 - blackfire agent (1.27.3) > 1.27.4 - [changelog](https://packages.blackfire.io/binaries/blackfire-agent/1.27.4/CHANGELOG) ### Added extensions - sqlsrv (5.6.1) - [changelog](https://pecl.php.net/package-changelog.php?package=sqlsrv) - pdo_sqlsrv (5.6.1) - [changelog](https://pecl.php.net/package-changelog.php?package=pdo_sqlsrv) ### Updated command line tools - `convert` ImageMagick (7.0.8-60) > 7.0.8-66 - [changelog](https://imagemagick.org/script/changelog.php) # Us against them as a spectator from the sidelines Source: https://blog.fortrabbit.com/us-against-them Created: 2026-05-06 Author: Frank Lämmer Tags: opinion > A German company on American infrastructure serving a global customer base. On EU data sovereignty, and what European should mean. - US people: No EU tech please. - EU people: No US tech please. ## European alternatives Websites such as [european-alternatives.eu](https://european-alternatives.eu/) and [eutechmap.com](https://eutechmap.com/) are having a moment. I would like to submit fortrabbit, but: > For infrastructure/hosting providers, "European" should not simply mean "a European brand on top of a US hyperscaler." If the core service is essentially reselling AWS/Azure/GCP, we may exclude it or label it clearly. So, we are just a "brand on top of a US hyperscaler"? _NOTE: The EU alternatives websites mentioned above are not a grass root inititaves, but commercial offerings. You can buy to get reviewed and ads there. This one is: [www.eucloud.tech](https://www.eucloud.tech)._ ## Sales perspective > As an online agency based in Germany we want to offer our clients 99,9% security and data sovereignty. That line was from a sales chat (Kirby CMS prospect). I doubt that there is a strict relation of security and data sovereignty. How to measure 99.9% security? But the point is the missing trust - not in us particularly, but in our partners. ## Global economic tension affects us The European Commission has recently opened investigations into Amazon Web Services (AWS) regarding its cloud computing practices, focusing on potential anticompetitive behavior and whether AWS should be designated as a gatekeeper under the Digital Markets Act. We got a "Request for Information" for case: "DMA.100033 - Amazon - cloud computing services" too. It looked more phishy than legit. I filled that long and cryptic form, mostly explaining why none of it applies to us. At about the same time Amazon launches the AWS European Sovereign Cloud, with a [website](https://aws.eu/en/). Would it convince my sales prospect? I doubt it. From my point of view, this echoes GDPR's launch (see [blog post](/fortrabbit-is-gdpr-ready)): good intentions, bad execution. Now everyone claims GDPR/CCPA compliance. I doubt it. ## Global by design Our niche PHP target audiences are spread across the globe. So, fortrabbit is global by design. 50% of our customers are from the US, with also a big customer base in the UK. The rest is mostly EU, Asia emerging. ## US tech is often better and hard to avoid We explored IaaS alternatives - specifically Hetzner - (see [blog post](/infra-research-2024)), but settled with AWS for the new platform as well. It's more expensive, but it has the tech we want. It also looks the most compelling in terms of environmental impact to me. We did not take that lightly. We still have an eye on UpCloud as a potential infra provider, as it is positioned as an [European alternative](https://european-alternatives.eu/product/upcloud). But their data centers are mostly operated by Equinix and Digital Realty, both US companies. Is it really an Eurpoean alternative then? ## It's not only infra Even if we switched the bare metal layer, we'd still rely on other US services: - Customer chat: Intercom (hm) - Billing: Stripe (tech is really good) - Deployment: via GitHub (we plan to add more services) - The list goes on We are planning a CDN integration. Of course Cloudflare is the most obvious choice. Beside the tech aspects, we also consider overall trust. And in that regard, for me, even with some bad press, Cloudflare may look more compelling than Bunny CDN. ## What we do Here we are, trying to implement good privacy standards on top of badly regulated businesses. - Collect only essential customer data, kept as briefly as possible, see :ContentLink{text="data collection and retention" prefix="www" href="/legal/data-protection/data-collection"}. - Take security seriously. Where possible, personal data is locked and encrypted. - Don't do shady marketing, sharing customer data with hundreds of business partners. - Carefully select and re-evaluate services we share customer data with. See our :ContentLink{text="sub-processors list" prefix="www" href="/legal/data-protection/sub-processors"}. - Try to be as transparent as possible about our customer relation. See our large :ContentLink{text="legal section" prefix="www" href="/legal"}, including policies for data processing. ## Requirements matter Most of our customers are using fortrabbit to host websites that are fully public anyhow. Some of our customers run web apps that collect their own user data. We try to educate developers about the risks and technical measures to protect that data as much as possible (encryption for example). We don't suggest to store sensitive data with our services, specifically health related data. I don't want to vote for "nothing to hide, nothing to fear", it's just that different projects have different requirements. ## Closing lines I enjoy living in the EU with strong consumer rights. Does it protect me against [unsolicited business proposals](/cold-outreach) or robotic sales calls? No! I believe global cooperation is better than fragmentation - for humanity and business. We don't need 'US against them' or 'EU against them'. - We don't want to pick a side. - We gravitate towards the best tech. - Our business can only thrive globally. - We are concerned about big tech too. - We care about privacy. # New platform now available in US Source: https://blog.fortrabbit.com/us-data-center-new-platform Created: 2026-06-02 12:11:03 Author: Frank Lämmer Tags: changelog > fortrabbit apps can now be hosted in the US data center on the new platform. Ten years ago, in February 2016, we launched our first US data center location — see [our 2016 US launch announcement](/hello-us). Now we are doing the same for the new platform (currently still in beta). Like before, the US data center location is North Virginia. In AWS lingo it is also known as data center US East (N. Virginia), or `us-east-1`. Our region ID is `us-e1a`. The new platform is still in beta (since November 2025). The bar is 95% feature parity with the old platform, thoroughly tested under real-world conditions. We do not have an ETA for the public release, but we expect it to happen this year (2026). The old platform will continue to be supported in the meantime. - :ContentLink{text="New and old side by side" prefix="docs" href="/platform/new/new-and-old"} It also gets us closer to the big migration project, where we plan to move remaining clients from the old platform to the new platform — we have no timing for that yet. More details will follow. Our vision is to be available in more data center locations worldwide. That is one of the reasons we had to build an entirely new platform — operating multiple locations has become more manageable, though it still requires careful consideration of efforts and costs. We also have ideas for a CDN integration, which will reduce latencies. :ContactUs{text="Let us know"} which location is missing for you! And by the way. Here is a promo code providing free hosting in the new platform for 1 month: `HELLO-US` - limited availabilty. --- The sections below walk through the practical details: ## How to choose a data center for a new app 1. Sign up or log in to the [dashboard](https://dash.fortrabbit.com) 2. Hit the "Create an app" button 3. **Choose the region location when asked** 4. Complete the remaining steps :BlockLink{title="Create a new app" path="/new/app"} The data center location does not affect billing currency — that is determined by the payment method. ## How to copy an app to a different data center There is currently no automated way to clone an app to another data center location, but it can be done manually: 1. Create a new app with the desired data center location 2. Deploy your code and content to the new app 3. Migrate your database (if you have one) 4. Test everything 5. Route DNS to the new app 6. Delete the old app Feel free to :ContactUs{text="contact us"} if you need help. ## How to create a new payment method with USD You cannot switch the currency of an existing payment method, but you can create a new one with USD selected: 1. Log in to the dashboard 2. Create a new payment method 3. Fill out the form and select USD as the currency :BlockLink{title="Create a new payment method" path="/new/payment-method"} Note that USD is only available for non-EU countries. See the :ContentLink{text="currency rules" prefix="docs" href="/platform/billing/currencies"} for details. ## How to change the currency To have apps billed in a different currency, move them to a payment method with the desired currency: 1. Log in to the dashboard 2. Navigate to the app you want to move 3. Hit the "change" button next to the payment method 4. Choose or create a payment method with the desired currency This only affects billing — no downtime, no team changes, and no change in data center location. You will notice that the app appears on two invoices for the current month: the old payment method up until the switch, and the new payment method from that point on. # Use Codio with fortrabbit Source: https://blog.fortrabbit.com/use-codio-with-fortrabbit Created: 2013-11-14 Author: Ulrich Kautz Tags: webdev > Connect the Codio web IDE to a fortrabbit app and deploy straight from the browser over git. The setup, in a few steps. Just a quicky: How to use [Codio](https://codio.com/) and fortrabbit. Codio is a new, amazing online code editor. As it supports deploying your code via Git, there is nothing stopping you from connecting it via fortrabbit and code away! ## Preprarations Of course you need a Codio and a fortrabbit account. Also create a new App with fortrabbit (or use an existing one..). ## Connect Codio and fortrabbit First you need a Codio (and of course a fortrabbit) account. Once you've signed up, just click on the "Codio" button in the upper left corner and choose "Account..". Now switch to the "SSH Key" tab and copy the key. Login to fortrabbit, go to your App and add the Key in the Git tab. Once this is done, you can create a new project on Codio by pasting your App's Git URL (can be found in the App's overview in the dashboard). ## Hello World & first deploy If you've cloned a new App, then it contains no files. So just create an `index.php` and fill it with something important: ![Write the index.php file](/../blog-assets/img/codio/05-Say-something-important.png) Open the Git console (Tools -> Git -> Command Line) add your new `index.php`, then commit and push: ![Add index.php to Git](/../blog-assets/img/codio/06-Add-indexphp.png) ![Make a commit](/../blog-assets/img/codio/07-Commit-changes.png) ![Push to fortrabbit](/../blog-assets/img/codio/08-Push-to-fortrabbit.png) And there you go. Thats about it. The response should look like this: ![Push to fortrabbit](/../blog-assets/img/codio/09-Push-results.png) ## And what about composer? Sure thing. Create your `composer.json` file in Codio. I've put `slim/slim` in it, for this demo: ![Create the composer.json file](/../blog-assets/img/codio/10-Make-composer-json.png) Now the same again: Add, commit and push. Mark the `[trigger:composer]` part in the commit message: ![Add composer.json to Git](/../blog-assets/img/codio/11-Add-composer-json-to-git.png) ![Make commit with trigger message](/../blog-assets/img/codio/12-Make-commit-with-composer-trigger.png) ![Push to fortrabbit](/../blog-assets/img/codio/13-Push-again.png) And in the push response message you can see that composer is installed. ![Push to fortrabbit](/../blog-assets/img/codio/14-All-Done.png) And that's it for now. [Codio](https://codio.com/) is not the only text editor for your browser. There are also: [CodeEnvy](https://codenvy.com/), [Cloud9](https://c9.io/), [CodeAnyWhere](https://codeanywhere.net/), [Koding](https://koding.com/), [FriendCode](https://friendco.de/), [Neptune IDE](http://neptunide.com/) and probably a few others. Also there is also the great [CodeMirror](http://codemirror.net/) project. Want more? Check out our huge list of [developer facing services](https://docs.google.com/spreadsheet/ccc?key=0An6rx68cKNFNdDNYdFdSSTNzZXl5eGRSY0ZxSW10aHc&usp=drive_web#gid=1) and out old post about [web IDEs](/about-new-online-text-editors). # Vertical browser tab challenges Source: https://blog.fortrabbit.com/vertical-browser-tabs Created: 2025-06-12 09:48:22 Author: Frank Lämmer Tags: webdev > Vertical browser tabs move the tab strip to the side, which quietly complicates web development if the pattern ever goes mainstream. ## Classical horizontal browser tabs ```plain ┌──────────────────────────────────────────────────┐ │ Tab1 │ Tab2 │ Tab3 │ Tab4 │ Tab5 │ + │ │ ├──────────────────────────────────────────────────┤ │ https://example.com │ ├──────────────────────────────────────────────────┤ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────┘ ``` Traditionally, browser windows are shown as tabs with a navigation located at the top of the browser. We all learned those patterns over the past decades. Many other programs now offer similar tabs. Every desktop browser has that, which I care about here. ## New vertical browser tabs ```plain ┌──────────────────────────────────────────────────┐ │ https://example.com │ ├──────┬───────────────────────────────────────────┤ │ Tab1 │ │ ├──────┤ │ │ Tab2 │ │ ├──────┤ │ │ Tab3 │ │ ├──────┤ │ │ Tab4 │ │ ├──────┤ │ │ Tab5 │ │ ├──────┤ │ │ + │ │ └──────┴───────────────────────────────────────────┘ ``` Some browsers can show tabs on the (left) side and I think that makes a profound difference in how websites and web applications feel. ## Browser support for vertical tabs | Browser | Vertical tabs | | ------------- | ------------: | | Google Chrome | ❌ | | Safari | ❌ | | Firefox | ✅ | | Edge | ✅ | | Brave | ✅ | | Vivaldi | ✅ | | Arc | ✅ | | Zen browser | ✅ | I discovered vertical tabs with Arc - a nice implementation with groups (spaces). At the time of this writing many browser already support vertical tabs. But vertical tabs UI can only become mainstream with support by Google Chrome. Safari has a vertical menu for tab groups, but I consider that something else. Vertical tabs in Firefox look ugly to me. Details differ. ## Pros I used vertical tabs for a while now and in general I like them. Although maybe it's the shiny new object syndrome? What I like: - More readable page titles in tabs - Vertical scrolling if a lot of tabs are open - Websites feel more like web apps (skip to content) - Hide tabs to get screen estate back ## Cons I use the browser 12 hours a day. Maybe vertical tabs for pro users like me only? - Sometimes I have trouble recognizing the active tab - Vertical tabs occupy precious screen estate (see below) ## Challenges Designing a responsive layout that also supports view ports with vertical tabs is yet another challenge for web developers. I am surprised how many websites and web apps are semi broken. Some are displayed in mobile mode, hiding important navigation behind a burger or overlaying elements, just because I have the vertical tabs open and a breakpoint was reached. ## My experience so far I am about to finish the design system for our new web properties. I dog fooded myself vertical tab screen sizes on smaller and larger screens. With some trial and error I was able to get a decent look on all the different sizes (small devices are not that important for us). ![Vertical tabs in the Zen browser](/images/vertical-tabs-zen-browser.png) For our new dashboard the main navigation is a vertical sidebar on the left side. It's kinda hard to see where the browser UI ends and where the website UI starts, particularly as the dark mode of the website doesn't play well with the darkish browser UI. ### Considerations Tailwind CSS offers some standard media queries for targeting different screen sizes. Thankfully, it's not opinionated on how those may be used, but screen size assumptions may need to be treated with more care. - **Add more media query breakpoints?** Maybe. - **Yet another media query?** `@media only screen with verticalTabs and (max-width: 600px)`. Hm. - **Container queries instead of outer window size media queries?** Maybe. ## Fluid layout Fluid CSS design might be part of a solution too. What the hack are breakpoints anyway? Why does a layout need to break? Can't it be fluid, always look great? We have responsive units like %, vw, vh. And we have the wonderful clamp function. So we can have tamed fluid sizes for all space units (margin, padding) and font size too. ```css /* Simplistic example */ /* Untested show idea */ h1 { font-size: clamp(1.5rem, 3vw, 4rem); } ``` At some point a three column layout may need to wrap to a two column layout, but I can imagine to achieve that without media queries Certainly something I would like to explore more, unfortunately missing time to dig deeper into it. I have started working on a fluid linear scale design system with my former Teutonic CSS system. I don't think that such ideas exist in Tailwind world. # Vibe coding an RSS feed - how hard can it be? Source: https://blog.fortrabbit.com/vibe-coding-an-rss-feed Created: 2026-02-06 Author: Frank Lämmer Tags: chronicles > Building RSS feeds for a Nuxt Content blog with fuzzy prompts and little supervision. What the AI got right, and where it went off. This blog runs on a `Vue.js -> Nuxt -> Nuxt Content` stack and is statically generated. So far, so standard. Now, what's missing is RSS feeds. Not only for the main feed, but specifically for the tags, so one can subscribe to specific topics. ## A good vibe coding experiment candidate Building RSS feeds for this blog has been in the backlog for over a year. But there was always something more important to do. The original idea was to leverage some plugin for that, specifically [nuxt-feedme](https://github.com/helltraitor/nuxt-feedme). But we are a bit hesitant depending on plugins as they can become a hustle to setup and maintain over years. Both, our tech layer and RSS feeds are well documented. An RSS of a blog is not a critical feature. Why not prompt it into live? What really is the difference to a plugin in this case? There is a chance that the specific AI code generated is even better for us. It does what we want, nothing more. We can extend it (hopefully). It's not critical. We can also throw it away and recreate it from scratch. Unlike other parts of our web properties, this is not required to be maintained by humans. Of course we want to see what it does and how, but it does not need to match our high standards, as it is just a periphery feature. It only needs to do one well defined isolated job and it does not matter much how we will get there. I don't really consider myself a developer. AI coding is tempting for me. It helps me prototype ideas, speed up my tasks and reduce load from my colleagues. So I asked GitHub Copilot to create this for me. It took a couple of iterations. And I had to correct it along the way, maybe because of ambiguous prompts? Anyway, it was fun watching the agent iterating over the problem and testing the result over and over again. There is always something to learn. I checked the generated feed a couple of times, before I finally filed a PR in good faith. ## The result My colleague Rafik caught a major issue, which I actually should have checked as well: Apart from the RSS feed working as intended, the whole blog couldn't be exported anymore. His reply: > This issue is an example of the biggest problem I have with LLM assisted coding and why I couldn't see myself just letting it run willy-nilly on a codebase. After creating the main feed at `/feed`, it tries to create the other feeds at `/feed/tag/changelog` for example. But since `/feed` is already created as a file, Nuxt prerenderer tries to create the subdirectories for the sub feeds and it fails. I tried prodding AmpCode to try to solve it for the past 2 hours and it too couldn't see the issue. I had to actually trace the code to see the logical error. We still have a ways to go before they can be let loose if we're being honest. ## Learning Expect the unexpected. Regardless of vibe coding, in hindsight it's pretty clear that tinkering with the build process can of course break the build process. Even a seemingly uncritical feature can have side effects. ```raw Software development without AI ░░░░░░░░░░░░░░████████████████████░░░░░░░░░░░░░░ Concept work Coding Testing Software development with AI ░░░░░░░░░░░░░░░░░░░███████████░░░░░░░░░░░░░░░░░ Concept work Coding Testing (Idea stolen from the internet, but I forgot where) ``` We ended up using the vibe coded feature. But it was more 'expensive' than originally anticipated. This does not consider other costs of AI, like energy consumption for this specific task. Is this unreliability part of the AI rollout plan? As long as we feel in control, we may not revolt against it? Are we the frog in the water that slowly gets hotter? > Herr, die Not ist groß! > Die ich rief, die Geister > Werd ich nun nicht los. > —Goethe (Der Zauberlehrling) ## Last not least The feeds are here now. We blog about webdev, developer culture, business hustles and sometimes even about PHP: - [fortrabbit main RSS feed](https://blog.fortrabbit.com/feed) - [fortrabbit changelog RSS feed](https://blog.fortrabbit.com/feeds/tag/changelog) - [fortrabbit webdev RSS feed](https://blog.fortrabbit.com/feeds/tag/webdev) --- - [Our AI usage policy](/legal/policies/ai-usage-policy) # FuelPHP on fortrabbit Source: https://blog.fortrabbit.com/video-install-fuelphp-on-fortrabbit-with-git-and-phpstorm Created: 2012-10-25 Author: Ulrich Kautz Tags: webdev > This video show you how to install FuelPHP on fortrabbit with Git and PhpStorm. We are continuing our video series by popular demand!. This is the fourth video of our screen-cast series. Here we are showcasing worst practices of PHP development & deployment on our sophisticated hosting platform. Learn here about one way (out of many) to install the framework **FuelPHP** on the fabulous fortrabbit PHP hosting platform. See the handy PhpStorm IDE, the fortrabbit web GUI and gorgeous Git version control in action. Please enlarge the video and switch to HD to get the details. ### Step by Step As always: To reproduce all steps, we assume you have an existing App on fortrabbit with your SSH setup for Git access. Our demo App is called "app-demo" - replace this with your App's name. 1. Clone repo from fortrabbit 2. Download & extract FuelPHP 3. Set the document root path in the fortrabbit control panel 4. Modify the .htaccess file 5. Add, commit & push to deploy 6. See the results in the browser 7. Done ### Further Readings * [FuelPHP Framework](http://fuelphp.com/) by the happy ninjas * [PhpStorm IDE](http://www.jetbrains.com/phpstorm/) * Music: [b-rog] - [Racing Thoughts](http://soundcloud.com/b-rog/b-rog-racing-thoughts) * [Getting started with FuelPHP](http://net.tutsplus.com/tutorials/php/getting-started-with-the-fuel-php-framework/) a tutorial by Phil Sturgeon ### The other videos * Video1: [PhpStorm and fortrabbit](/?p=973) * Video2: [Laravel on fortrabbit](/?p=961) * Video3: [Slim PHP on fortrabbit](/video-install-slim-php-on-fortrabbit-with-git-composer) # Install Laravel on fortrabbit with Git Source: https://blog.fortrabbit.com/video-install-laravel-on-fortrabbit-with-git Created: 2012-10-13 Author: Frank Lämmer Tags: webdev > A screencast walking through installing Laravel and deploying it to fortrabbit with git, from an empty folder to a running site. ## Video: Install Laravel on fortrabbit with Git _This is the second video of a new screen-cast series where we are showing off our worst practices of PHP development & deployment. Plug: Of course all videos are somehow related to our platform. _ In this tutorial screencast video you see one way (out of many) to install the classy PHP framework Laravel on the splendid fortrabbit PHP hosting platform. See the handy PHP Storm IDE and the gorgeous Git version control in action. Learn how you can change the doc root folder to your App in the fortrabbit control panel. It only takes a Git push to deploy everything and this happens within seconds. It only needs 20 seconds on the first commit & push - next will be single digits, of course. At the time of this writing Larvavel 3.x was the latest stable available version. We are really excited about the next version which is about to come out soon. This video was filmed in full color in Linux cinemascope. Please enlarge or use fullscreen mode and switch to HD to get the details. This video was written and produced by our chief engineer Ulrich Kautz. ### Step by Step 1. Clone repo from fortrabbit 2. Download and extract Laravel 3. Set document root for App 4. Modify index.php and .htaccess 5. Commit & push to deploy 6. Done ### Further Readings * [Laravel Framework](http://laravel.com/) by Taylor Otwell * [More Laravel How To Videos](http://heybigname.com/series/laravel) by Shawn McCool * [PHP Storm IDE](http://www.jetbrains.com/phpstorm/) * Music: [drb] - [Couldn't wait](http://soundcloud.com/b-rog/couldnt-wait) * [Install Laravel on fortrabbit](http://support.fortrabbit.com/customer/portal/articles/769508-install-laravel-3-x) < more infos on our support pages # Slim PHP on fortrabbit Source: https://blog.fortrabbit.com/video-install-slim-php-on-fortrabbit-with-git-composer Created: 2012-10-14 Author: Frank Lämmer Tags: webdev > This videos shows you how to set up SlimPHP on fortrabbit with Git and Composer This is the third video and last (for the time being) of our screen-cast series where we are showing off our worst practices of PHP development & deployment on our hosting platform. Learn here about one way (out of many) to install the PHP micro framework Slim on the fabulous fortrabbit PHP hosting platform. See the handy PHP Storm IDE, gorgeous Git version control and the funky dependency manager PHP Composer in action. The magic, you can only do on fortrabbit, happens in minute 1:18 where we use the special keyword "[trigger:composer]" in the commit message to run the Composer installer on the remote server. This video was filmed in full color in Linux cinemascope. Please enlarge or use fullscreen mode and switch to HD to get the details. This video was written and produced by our chief engineer Ulrich Kautz. ### Step by Step 1. Clone repo from fortrabbit 2. Create index.php, composer.json and .htaccess 3. Commit with trigger commment ([trigger:commit]) 4. Push to deploy 5. Done ### Further Readings * [Slim Framework](http://www.slimframework.com/) by Josh Lockhart * [PHP Storm IDE](http://www.jetbrains.com/phpstorm/) * Music: Morg - [ÖverKill](http://soundcloud.com/mc-morg/morg-verkill) * [Install slim on fortrabbit](http://support.fortrabbit.com/customer/portal/articles/780586-install-slim-framework) < more infos on our support pages * [Composer hook on fortrabbit](http://support.fortrabbit.com/customer/portal/articles/717047) < more infos on our support pages # Symfony2 on fortrabbit Source: https://blog.fortrabbit.com/video-symfony2-on-fortrabbit Created: 2012-11-01 Author: Frank Lämmer Tags: webdev > A screencast showing one way to set up Symfony 2 on fortrabbit, recorded for the Symfony Live event in Berlin in 2012. This is the fifth video of our screen-cast series where we are showing off our worst practices of PHP development & deployment on our sophisticated hosting platform. This is our in-official contribution to the [Symfony Live Event 2012](http://berlin2012.live.symfony.com/) here in Berlin. Learn here about one way (out of many) to install the famous **Symfony2** (a popular PHP framework to build web projects. Also the base for some CMS systems, like the new Drupal8) on the fabulous fortrabbit PHP hosting platform. See the ultra cool text editor Sublime Text 2, the fortrabbit web GUI, gorgeous Git version and PHP Composer in action. This how-to is targeted to developers adept with the shell. Please enlarge the video and switch to HD to get the details. This video was written, directed and produced by our chief engineer Ulrich Kautz. ### Step by Step _As always: To reproduce all steps, we assume you have an existing App on fortrabbit with your SSH setup for Git access. Our demo App is called "app-demo" - replace this with your App's name._ 1. Use the shell to download and install PHP composer locally 2. Use the shell to install Symfony2 via PHP composer to a local folder 3. Composer is doing all the dirty work (FFWD) 4. Init Git and add the fortrabbit remote branch 5. Push to fortrabbit and trigger the remote composer with a special comment in the commit message 6. The fortrabbit platform is doing all the dirty work (FFWD): 1. Syncing the remote repo into the web-space 2. Running composer on the remote server to install all dependencies 7. Create a Symfony2 bundle (where? what? why?) 8. Set the doc root path in the fortrabbit control panel to match best Symfony2 conventions 9. Grab the .htaccess example rules from the fortrabbit help and paste them in the project (WHY?) 10. Push to deploy all changes to the fortrabbit web servers 11. See the results in the browser ### Terminal Transcript ```bash $ cd projects/ $ curl -s https://getcomposer.org/installer | php $ php composer.phar create-project symfony/framework-standard-edition AppDemo 2.1.2 $ cd AppDemo $ git init . $ git remote add origin git@git1.eu1.frbit.com:app-demo.git $ git add -Av $ git commit -am 'Initial [trigger:composer]' $ git push origin master $ php app/console generate:bundle # modify AppDemo/web/.htaccess -> add the following after "Rewrite Engine On" RewriteCond %{REQUEST_URI} \.php/ [NC] RewriteRule ^(.*)\.php/(.*)$ /$1.php [NC,L,QSA,E=PATH_INFO:"/$2"] $ git add -AV $ git commit -am 'Bundle & .htaccess' $ git push origin master ``` ### Further Readings * [Symfony2 Framework](http://symfony.com/) by SensioLabs * [Sublime Text](http://www.sublimetext.com/) the text editor * [Music: Broke for free The Great](http://freemusicarchive.org/music/Broke_For_Free/Slam_Funk/Broke_For_Free_-_Slam_Funk_-_03_The_Great) ### The other videos * Video1: [PhpStorm and fortrabbit](/?p=973) * Video2: [Laravel on fortrabbit](/?p=961) * Video3: [Slim PHP on fortrabbit](/video-install-slim-php-on-fortrabbit-with-git-composer) * Video4: [FuelPHP on fortrabbit](/?p=1062) # Hello world with PHPStorm Source: https://blog.fortrabbit.com/video-yet-another-hello-world-with-phpstorm Created: 2012-10-12 Author: Frank Lämmer Tags: webdev > A screencast deploying a simple hello world from PHPStorm to fortrabbit, and a note on how much work tutorial videos actually are. How many times have you read something like this: "This is the first video of a new upcoming screen-cast series…"? And how many times this was the only video of the planned sequel? Producing tutorial videos is a hassle. We know that. But screen-casts are a great way to show how something really works. OK, here we go: _This is the first video of a new how-to-videos series where we are showing off our worst practices of development & deployment on our PHP platform. _ Learn here about one way (out of many) to set up a quick Hello World example on the fabulous fortrabbit PHP hosting platform. See the handy PhpStorm IDE, gorgeous Git version control and the funky dependency manager PHP Composer in action. Sublime Text is not the only code editor as you can see - PhpStorm is a full featured but lightweight IDE for all operating systems. It helps you to understand what's going on in your PHP code. This video was filmed in full color in Linux cinemascope. Please enlarge or use fullscreen mode and switch to HD to get the details. This video was written and produced by our chief engineer Ulrich Kautz. ### Step by step 1. Clone repo from fortrabbit 2. Create a simple "Hello World" index.php 3. Commit & push to deploy 4. Done ### Further readings * [PHP Storm IDE](http://www.jetbrains.com/phpstorm/) * [Music: Tour - Enthusiast](http://freemusicarchive.org/music/Tours/Enthusiast/) # Web hosting and open source Source: https://blog.fortrabbit.com/web-hosting-and-open-source Created: 2025-03-17 10:46:16 Author: Frank Lämmer Tags: opinion, changelog > It's complicated. The relation between open source and web hosting from our point of view ## Our story We started our PHP hosting business around 2012. Composer was just released. PHP 7 on the horizon. We aimed to create a hosting service for modern PHP websites and web applications. The young Laravel community helped us getting started. Back then, I did not realized, how crucial and fragile this initial support by the community and those early adaptors was. Blinded by my ego, I thought that our great talent and superior service was the reason for initial success. It did not even crossed my mind to invest in a partnership with Laravel, I took all that for granted. In 2014 Taylor Otwell (Laravel) launched Forge, a hosting service for the Laravel community. This was a big blow for our business, killing our stable inbound channel over night. Luckily only half of our customers where using PHP frameworks to create web applications. The other half was classical websites usually done in a CMS. We where not interested in hosting WordPress. So we invested to get some visibility with the young Craft CMS scene. With modern paradigms Craft CMS matched our platform quite well too. We really digged it. This time we invested to have a formal partnership with it's creators (Pixel & Tonic). We became recommended hosting partners, which in return would result in a steady stream of signups. Eventually, Pixel & Tonic ended our partnership as they prepared to launch their own Craft Cloud hosting service. Another blow for us, not only business wise but also emotional. ## Open source software and hosting > A lot of people who work on open-source software don't mind making money elsewhere. They aren't anticommercial. -Jimmy Wales Open source projects require funding. Entrepreneurship can be an effective model. A related business can provide the foundation for the independent development of the OSS project. From a business perspective, the popularity of an OSS project can generate the leads. For website or web application software, a hosting solution is an ideal match, as it is a service that users of the software will need anyway. They will be happy to support their open source heroes. Vercel is another hosting service with a tight open source software connection. The popular Next.js (React) framework comes from Vercel. Nuxt, the Vue based alternative has Nuxt Studio, an add-on service for Nuxt content. The french PaaS Platform.sh is very close to Symfony project. The Symfony founder Fabien Potencier now works for them. Laravel Cloud launched recently. That's another hosting business from Laravel Inc to monetize their reach. From my perspective the Laravel eco system is closing down making it even harder for us and others to be seen as an alternative. ## Our strategy We don't have the resources to invest heavily in OSS. We lack time, financial resources, energy, and a viable idea to build our own OSS business vehicle. Our focus is solely on providing a web hosting solution. We aim to create a good product - [new platform in the making](https://new.fortrabbit.com). We can thrive with a tiny market share. We bet on the long tail of a vivid PHP community with many open source frameworks and content management systems. We shamelessly use OSS trademarks to advertise our services, demonstrating that our platform is a good match and that we know a bit about running such software. ## In closing Let's revisit the WP-Engine / WordPress controversy. Initially, I sympathized with the idea of a greedy web hosting company profiting from WordPress without giving back. Automattic, Matt's company, made $710M in revenue, while WP-Engine made $400M in 2024. It seems Matt is not the lone open source maintainer in need of support. I can't judge how much WP-Engine has contributed or should have contributed. Our cost structure is very different from traditional hosting providers. We have [high infrastructure costs](/infra-research-2024), almost no marketing budget, while most of our energy goes into product development. Our ability to contribute back to OSS is very limited. We use a lot of open source software to run our business, our clients are using a lot of open source software to interact with our services too. We couldn't do without. Some of those open source projects are already well funded. But there are others projects that can benefit from funding. Open source maintenance can be stressful, lonely and financially unrewarding. Where possible, we plan to sponsor open source projects more. We also aim to contribute to write well researched feature requests or issues. # What happened to our old WebHosting? Source: https://blog.fortrabbit.com/what-happend-to-our-old-webhosting Created: 2012-07-02 Author: Frank Lämmer Tags: chronicles > What became of MISH, the bare-metal hosting platform fortrabbit ran in a Berlin data center before building a PHP cloud service. **tl;dr** We used to bring modern cloud technologies such as Git code management and consumption based billing to a standardized Hosting environment. Now we go the other way around and bring some essential standards to the cloud._ ## Past: The "MISH" Era We are running our own hardware for nearly four years now. Over two years in production with about 250 clients. Our own software MISH (Mish is Supreme Hosting) is not only our master control panel it is also a very specialized clustered and virtualized hardware architecture. MISH is very versatile and includes different aspects of WebHosting: Domain ordering and management, E-Mail Hosting including powerful tools to handle SPAM, powerful and scalable PHP hosting based on FastCGI, a Two Level Deployment Solution based on Git for developing websites. It has the fairest pricing model: very modular and consumption based, supporting all different kinds of usage. MISH also hosts our free accounting tool [webrechnung.info](http://webrechnung.info). The modularity and versatility of the MISH system allowed individual solutions. From a B2B-FTP-file-exchange to e-mail relaying, from small microsites to big apps with multi-million requests per day. ## Status Quo MISH grew over the years and became very extensive and complex up to a point, where we had to spent much more time maintaining than we could developing the system towards our goals. As it turned out, we produced much more ideas than we actually where able to realize: about 300 idea-tickets in our project management software; some big, some small, some major, some minor. Then there was this other huge elephant knocking at the door: The next generation of hardware. Yet another big and very expensive project and yet again the end of the tunnel became out of sight. So we sat down and thought about our situation and decided to "pivot": * Realize the most important ideas on a **new platform** NOW * Base the new platform in the cloud on Amazon AWS * Include our learnings and experience * Maintain the old platform as long as needed ## Marvelous Clouds (Good Bye Hardware - Hello Cloud) The move to AWS is a major turn in perspective for us. It does not only mean less profits - of course running our own hardware brings a bigger profit margin - but also less work and less responsibilities on our side. No more late night sessions in the noisy data center replacing old disks with new ones or checking RAM modules for corruption. Less time in Low-Level SysAdmin stuff, such as tracing bugs in network bridging or CPU clock issues in the virtualization layer. This will give us more time doing what we really do good: Designing and building a cool platform where you can develop and host your Apps and Websites. In our old system our clients where already able to scale their hosting instantly at any time. But we where still stuck in big batches: New hardware capable of serving about hundred clients costs some money at once. You need to order, configure and install it. Then it should be packed with clients as soon as possible to return it's investment. All this hassle is gone, now. ### Dependencies We haven't, yet, much experience with AWS in production, but, so far, everything runs like a charm. Of course we have noticed and discussed the two bigger downtimes (US1 recently and the Ireland Stroke) they have had lately. For the end client the responsibility chain seems to get longer. But in fact there was and is always someone above us who can break things: The data center, your hardware is housed. If their networks uplinks or their power supply fails - yours does, too. Next would be the ISP providing the Uplinks: if they fail, the data center does and so do you. Now we are far more able to implement redundancy: all our services are in at least two different availability zones. We are able to access any amount of servers at any time: if some server fails with hardware issues, we simply start another. To sum it up, we have reduced the chance of a downtime for a particular website hosted in our infrastructure by far. We are confident to improve on our past uptime, which already was around 99,99%. ### Privacy Some people are concerned about privacy and "loosing the control of their data" in the cloud. Are you ready to run your business with us on servers in Ireland that are operated and owned by an US company? Do you consider industrial espionage a real risk? We can't answer this for you and we do understand your concerns. You need to answer that for yourself. ### What's up next? We are currently working full time testing the new platform and smoothing out some edges. In a few weeks a first private round (take a small survey to apply [here](http://fortrabbit.com)) will start. The old platform had great features for people like us: web developers. We took this even further in the design of our new platform: Developed for developers (by developers of course). It will include all of our technical experience and knowledge of real world developer needs. The platform itself will launch later this year. At the start it will not be as feature rich and versatile as the old system. The End of Life for the old MISH platform is scheduled for not earlier than April 2013. By that time we hope to have all important features from the old platform integrated on the new platform. Of course, we will assist all old clients moving to the new platform. # The meat market Source: https://blog.fortrabbit.com/what-the-hosting-and-the-meat-market-have-in-common Created: 2012-10-19 Author: Frank Lämmer Tags: opinion > Brutal price competition produces factory farming in meat and something similar in hosting. An illustrated argument about cheap. ![MeatHosting Illustration by Frank Lämmer](/images/meat-hosting.png) ### The meat market All experts agree that meat prices are much too low. The brutal price competition results in factory farming and the massive usage of antibiotics. That's not good - neither for the animals nor for us customers. We eat too much meat and get too fat. **How to fix it**: Go to your butcher of trust. Ask about the welfare of animals and meat quality. Eat meat more consciously. Vote for a party that supports meat market regulation. ### The hosting market Here competition is also driven by price dumping. Hosting plans are mostly compared by their price tags. Unlike animals bits and bytes are comfortable stored in a tight metal box. But legacy technology, ugly web interfaces and sloppy implementations cause headaches for us web developers. **How to fix it:** Go to your hosting provider of trust. Ask about the infrastructure and deployment. Calculate carefully what is more valuable, a cheap hosting offer or developing productivity? # Where to host my website now? Source: https://blog.fortrabbit.com/where-to-host-my-website-now Created: 2012-12-04 Author: Frank Lämmer Tags: opinion > IaaS, PaaS, bare metal, shared or managed hosting: how to decide, written for clients whose old hosting platform was being retired. Our old, bare-metal hosting platform MISH is in the sunset phase. This article should help our existing clients to decide where to host their stuff in the future. It's also meant as a general advice to anyone who is not sure whether a cloud PaaS provider is the right choice. If not: what alternatives are there? If yes: what other services need to be booked beside a cloud hosting platform? ## Is the new fortrabbit for me? You might head over to our [main website](http://fortrabbit.com) and check out the product features. In case you don't understand a word: it might not be the best product for you. Our old MISH hosting was far more broad-band - great for developers but also versatile enough to fit the needs of classical hosting. The new fortrabbit platform is _very_ specialized - the focus is on the needs of development and growing web applications. ## Real world needs Following some exemplary use cases and our advice for each of those. ### I just want to be online You might have a business for which the internet is not so important. You just need to be findable in google. People should be able to get in contact with you over the web. You don't sell anything online. You want a simple website to present you and your business. It doesn't need to change at all even for a long period. Think twice now - do you really need a website? Do you own domains you aren't using? Does your website feature a "Coming Soon" for years? Are the informations on your website up to date? Mind that local businesses, such as restaurants for example, can nowadays easily be found through services like [Foursquare](http://foursquare.com), google local search and [Yelp](http://yelp.com). In case you just need a kind of landing page for your real name that links to your various profiles in social networks you might check out a service like [about.me](https://about.me/). In case you still want a simple website: Consider to check out a shared hosting service. There are many, many of them out there. In Germany, for example: [1und1](http://1und1.de), [Strato](http://strato.de), [Hetzner](http://hetzner.de), [Host Europe](http://www.hosteurope.de/), [Domain Factory](http://www.df.eu/) and the list goes on. We know that there are many people only comparing prices in hosting offers. We strongly believe that [this is dead wrong](/what-the-hosting-and-the-meat-market-have-in-common) and that the quality of service should be the primary consideration (even though it's hard to compare). ### I want an e-commerce site You are running a web shop based on Magento, osCommerce or some other open source PHP software. We are a good choice for you. As any [other](/comparing-cloud-hosting-platforms) PHP PaaS provider, you can scale your resources based on business demands - think about Christmas sales. However, there are also great off-the-rack solutions by SaaS providers. For example: [Shopify](http://shopify.com) can host your shop. We have no experience with the service but it seems very versatile and customizable. [BigCartel](http://bigcartel.com) is another, easy to use E-commerce as a Service. ### I want a blog Of course you can run your WordPress, Moveable Type, Textpattern or whatever you want on our new platform without a hassle. You can utilize our sophisticated deployment using Git; even old-school workflows based on SFTP, if you are used to them. We are geared especially for anything including active development and critical for business. If you just want to write some stuff for hobby, you might consider to use a hosted blog service such as: [wordpress.com](http://wordpress.com) (WordPress as a Service), [Blogger](http://blogger.com) or [Tumblr](http://tumblr.com). Nerds might want to give [scriptogr.am](http://scriptogr.am) (which builds on dropbox) a try. ### I want a portfolio to showcase my work I guess you want to do something yourself when you have skills in frontend development - we give you the right tools do just that as easy as possible. In case you are a photographer, a designer or any other artist with no web skills you might consider, once again, using a Software as a Service for this. Good examples in the category might be: [Cargo Collective](http://cargocollective.com/), [CarbonMade](http://carbonmade.com/), [Behance Network](http://behance.net) (Design), [Dribbble](http://dribbble.com/) (UI) … ### I want web-space to transfer large files Some of our clients use FTP for file exchange. The graphic designer, might upload some large image files to the server and hand them over, using an HTTP-link, to the client. This is, in general, also possible with our new platform. But we are focused on website delivery. Keep in mind that storage and traffic are more expensive than they would be offered by specialized services. SaaS alternatives are: [DropBox](http://dropbox.com), [Google Drive](https://drive.google.com), [WeTransfer](https://www.wetransfer.com/) … ### I want a highly customized hosting Go ahead: ask us. Our enterprise solutions are tailor made for your needs. We can produce any amount of resources you might need in no time. In contrast to "old school" solutions: you pay what you use right now - you do not pay for future needs before you actually need them. However, there are still good bare-metal solutions. In Germany you can check out for example: [Unbelievable Machine](http://www.unbelievable-machine.com/), [SysEleven](http://www.syseleven.de/). ### I want to start lean and grow with my startup Well, that is exactly what we offer best. You can start with a modest amount of resources, while continuing to grow - as well in code and visitors. We support agile development patterns, allowing you to stage your App as often as needed. Resources are there when you've grown to need them. ### I want classical hosting (no cloud) with good support Do you just have prejudices or real concerns about the cloud? Please talk to us one more time. Anyways here are two German providers with a similar profile as our old hosting style: [Schokokeks](http://www.schokokeks.org/), [Ueberspace](http://uberspace.de/). We don't have any experience with them, but they look very pleasant and seem to give a professional support on an eye-to-eye level. ### I want to develop apps for my customers Yet again, we think we are the perfect match. Besides our easy and fast deployment, we (will) offer sophisticated tools to manage App ownership and developer access. Whether you are a full service agency, charging your customers for hosting and support, or a small group of developers, creating awesome Apps and websites and handing them over to the customer when finished. ## What you need when you move to the cloud PaaS providers, like us, are more specialized. We provide the best we possibly can for delivering your websites and offer supporting services via third party add-ons - but this leaves some requirements, you still have, out. So here they are: ### Domains You got us. Just as all other cloud hosting platforms the fortrabbit PaaS does not support domain registration. Well it's "decoupled" - you know. Actually we are still thinking about integrating domain management in our platform. We have done this in the past and know how to it. But the whole domain ordering process is really a hassle. There are tons of special cases and conditions and in some many cases we had to intervene manually. And to be honest: the money is no good - as long as you do not make this your primary business. At the current state, we leave this to third party providers which concentrate only on this - so they are good at it and we can concentrate on keeping up our end. # Why a GUI and not a CLI Source: https://blog.fortrabbit.com/why-gui-not-cli Created: 2023-08-28 09:36:38 Author: Frank Lämmer Tags: chronicles > Developers reach for the terminal first, so why did a hosting platform for developers start with a graphical dashboard instead? We are currently working on a new version of our PHP hosting platform. Early in the process we asked ourselves: How will our clients want to interact with our services? Being developers ourselves, the natural reflex was: > _Let's build a CLI and never ever leave the terminal again!_ Start with a CLI now and maybe build a GUI later on! Well. A CLI is of course sexy and considered to bring a good Developer Experience. But we don't think it's the best tool for all the tasks we need to cover. The fortrabbit dashboard is the place where customers can create apps, manage technical settings, route domains, edit billing-related data and collaborate with others. While it might be cool to create an app from the command line, it would be hard to communicate all the options and required details when making a binding booking. A web-based graphical user interface enables us to show complex data in a nice visual structure - think pricing tables, help boxes, visual feedback and error messages. That being said, GUIs often suck, because they require you to use a mouse. That's something developers don't like to do. So, our aim is to make our new dashboard accessible for keyboard enthusiasts. Something we would want to use ourselves. ## Ideas for a general fortrabbit CLI We pride ourselves on [Craft Copy](https://github.com/fortrabbit/craft-copy), a little command line tool to help deploying Craft CMS based websites to fortrabbit. It abstracts a couple of shell tasks in a small collection of useful commands. This is where a CLI for our services can shine - helping with deploying code and database changes, debugging issues, maybe accessing logs. Tasks you need to do often, tasks that are naturally related to the terminal. We have been poking around the idea to generalize the tool to match all kind of applications hosted here, Laravel (including Statamic and others), Symfony, maybe even WordPress. A fortrabbit deployment CLI. But it''s hard. Those software systems are all unique and we learned from Craft Copy that it takes some effort to keep up with the development of Craft CMS itself. Craft Copy also includes some custom magic specifically to make the Craft CMS experience smoother with fortrabbit. ## Wrap up So for now, it's: Start with a GUI and maybe build a CLI later on! Well. Product development is about saying no a lot of times. # Why we don't do 1-click installers Source: https://blog.fortrabbit.com/why-we-dont-do-1-click-installers Created: 2026-05-12 Author: Frank Lämmer Tags: opinion > Why fortrabbit doesn't offer 1-click installers — and the local-first workflow we recommend for shipping real PHP projects. ## The Time-to-WOW pitch Many cloud services compete on how quickly a new visitor can see something running. A short signup, a 1-click installer, a fresh WordPress / Laravel / Craft / Statamic dashboard staring back at you in ~~ninety~~ twenty seconds. It's a good demo. I think it's also misleading. ## A 1-click installer actually gives you nothing What you get is a blank install of someone else's reference template, running on a vendor-managed stack you didn't configure. Useful for a pitch — to users or to investors. Less useful for shipping anything. The reason: with the software we host — Laravel, Symfony, Craft CMS, Kirby, Statamic, WordPress — the fresh install is the empty room. Your project lives in the templates, plugins, theme, schema, content model and the code you write around all of it. None of that exists in a blank copy. You'd throw it away and start over anyway. So what's the point? The 1-click installer is a sales-funnel device. It demos the platform fast, gets the signup in fast, and lets the host claim "fastest deployment in the market." Having been in PaaS hosting for so long, I've seen many first-generation PHP PaaS come and go. Especially in venture-backed startups, the pressure to get an app running in seconds rather than "only" minutes seems to matter a lot. Same goes for Laravel Cloud, which launched last year. I don't buy in. I don't want to compete on such a bogus metric. Most projects are hosted for years. Of course you want to set up resources quickly and stay in control — you don't want to fax a hosting provider and wait for your server to be provisioned. ## Real life is local-first The honest workflow for a real PHP project is the one developers actually use: 1. Install the framework locally 2. Build out the project — code, templates, content 3. Deploy That's how our :ContentLink{text="install guides" prefix="docs" href="/guides"} describe it. That's how Laravel, Symfony, Craft, Kirby and Statamic recommend it themselves. Pushing the "click here to skip steps 1–3" button doesn't put you closer to a shipped project. It puts you further away — because now you have a deployed shell with nothing in it, and you still need to do steps 1–3. ## What we do instead We optimize for the developer who'll be hosting with us for years — not for the demo. That means we'd rather give you a slower first session that gets you to a real, working, locally-developed project than a faster one that produces nothing usable. - **Composer-first.** Real dependencies, a real `composer.json`, real version control over what's installed. - **Git push to deploy.** Connect a GitHub, GitLab or Bitbucket repo. Pushes trigger a deploy. Composer runs as part of the build. See our :ContentLink{text="git deployment docs" prefix="docs" href="/platform/deployment/intro"}. - **Documented local-first workflow.** Our :ContentLink{text="install guides" prefix="docs" href="/guides"} for Laravel, Symfony, Craft CMS, Kirby and Statamic all start at "set up locally." - **fortrabbit agentic skills.** Our agentic skills for AI coding assistants instruct the assistant to install your project locally first, then deploy. Same path as the docs — automated. We think the trade-off is worth it. It takes longer to see your first running site, but you get a deployment path you can actually scale into a production workflow. If you came here looking for "deploy a generic Laravel template in one click" — we don't have that, and we're not building it, at least not until we find a way to make it good. If you came here looking for the platform to host the Laravel app you're already building — that's us. See also: :ContentLink{text="No X" prefix="www" href="/platform/no-x"} for more of what we don't do, and why. # Why we don't do Add-Ons Source: https://blog.fortrabbit.com/why-we-dont-do-add-ons Created: 2016-02-29 Author: Frank Lämmer Tags: opinion > Insights why we will not offer an Add-On program soon and what we have instead ## What are PaaS Add-Ons anyways? Add-Ons are part of a standard PaaS offering. While the PaaS vendor runs the main service and has all the users, specialized vendor for X-as-a-Service can enhance the service offering by a certain functionality. To make live easy, the PaaS client can book the external service directly thru the PaaS provider. PaaS and Add-On provider connect via an API. Some Add-On providers provide their service solely on such a market place, others do it as a side offering. Billing is provided by the PaaS — the client will get one bill by the PaaS provider. PaaS and Add-On provider then share the revenue. ## Why we don't do it It's a really tempting tool to make our service more visible and versatile. We don't want to solve every problem on our own. Imagine an easy way to plug-in Elasticsearch or Redis. However, the devil is in the details: --- **The client side**: We see these drawbacks for clients using Add-Ons: ### Responsibility You — the PaaS client — have a contract with your PaaS. What happens when you book an Add-On from the PaaS provider? Have you just silently agreed to another Terms Of Service (the one from the Add-On provider)? What when something goes down: who is to blame? You will probably ask your PaaS provider and they will point you to the Add-On provider with whom you don't have any direct contract. ### Support Who you — the PaaS client — gonna ask when you have question or problems regarding the Add-On? You will use the support system of your PaaS. What happens next, is that a PaaS support agent must forward or at least assign your case to someone from the Add-On provider. ### Privacy You — the PaaS client — book an Add-On. Some of your personal data (probably your email address) is highly likely transferred to the Add-On provider. You don't know what data the PaaS and the Add-On provider have agreed to exchange and how it will be handled. Compare the with the standard oAuth procedure when you sign in to a service using Twitter, Facebook or Google: You have last say in what who will get. ### One to many, many to one We — the PaaS provider — currently have an App-centric design. So naturally you'll book the Add-On for a certain App. In the real world however, it is possible to use an Add-On for multiple Apps, or to even use one Add-On multiple times on one App. That's hard to design — it's fundamentally different to the app-centric approach. ### Evolving systems Add-On vendors — at least the cool kids — are following their own agenda. Some provide more than one service, have team features, offer login with 3rd party services (Goolge, GitHub) and other things that can't be adapted by an Add-On system. --- **The B2B side**: We see these drawbacks on the business relation between PaaS and Add-On provider as well: ### Business model fit We — the PaaS provider — currently offer a trial mode which includes all the features, only limited in time. Now, many Add-On providers offer a freemium mode which is unlimited in time but limited in resources. So that's not really a fit. Also the target audience must fit: if your Add-On is three times expensive as the hosting itself, it's not very likely that lot's of bookings will happen. ### Billing We have have a [consumption based billing](http://help.fortrabbit.com/billing) with a daily billing cycle — clients pay each month after usage. Add-On providers might have a subscription based model with fixed monthly plans — clients usually pay in advance. So how can we bring those different models together? How to make it fair and transparent for all sides? ## Asking the Add-On providers All of the above problems can be solved — and we like to solve hard problems. But at this point we were unsure if it will be worth the efforts. So we contacted our [A-list of Add-On providers](https://docs.google.com/spreadsheets/d/1UNUTiplOSfcJf-fpkvfdL717T7WfKBmC4wdAkO16cp0/edit) for a signal. The feedback we got proved most of our above own conclusions. ## What we do now We'll continue to bring our PaaS and the Add-Ons closer together. That's the most crucial part. So we will provide additional instructions in our help pages on how to combine our service with provider X and provider Y. Therefore we have also restructured our documentation and open sourced it. In a next step, we plan to bring voucher codes to the platform. So fortrabbit users can get a discount when booking Add-On provider X — or the other way around. See our new **[extending fortrabbit](https://help.fortrabbit.com#extending-fortrabbit)** help section. See the [help GitHub repo](https://github.com/fortrabbit/help) on how to contribute. # Worker Add-On released Source: https://blog.fortrabbit.com/worker-addon-released Created: 2013-08-07 Author: Ulrich Kautz Tags: changelog > We have a new Add-On: Workers! Learn about it and what you can do with it. **tl;dr**: The feature you most requested from us were [Workers](http://fortrabbit.com/feature/workers). We hear you! Here they are! Workers are extremely useful for scaling your App, because they allow you to outsource long running tasks in the background. To understand how they works you first might want to know why you want to use Workers in the first place: ## The standard e-mail example Say you build your new App. It features a user community, so you have some kind of sign-up process, probably with some kind of [closed loop authentication](https://en.wikipedia.org/wiki/Closed-loop_authentication) (aka double opt in), which requires you to send mails to the user. Imagine now your mail provider goes down, even only temporarily. Or it suffers some huge load and slows terribly down. Darn. Your sign-up doesn't work anymore. Even worse: the timeout of your mail transport blocks all requests and nobody can use your site anymore! Here is where Workers can help out. Instead of sending mails directly, you put them in some kind of queue. This can be a real queue, like [Amazon's SQS](http://aws.amazon.com/sqs/), [Iron MQ](http://www.iron.io/mq), [Rabbit MQ](http://www.cloudamqp.com/), or simply your good ol' database. Key is, that you poll this queue (or search the database) later on, from a persistently running process in the background. This process then sends all the mails to the users. If your mailing is up and running: great! They get send immediately. If not: well, they are are delayed until things get better. But your users don't get the mail immediately, so they cannot really sign-up, you say? Right, but at least the sign-up process does not timeout and your site is still usable for anybody else. An improvement, I'd say. Also most of the time you rather experience a temporary performance degression of your mail transport, because it gets a huge load from somebody else. So in this case, the perceived performance of your site stays the same, all the time, only sometimes mails get send a bit later than expected. ## The resource hog example Still not convinced? Ok, here another scenario: Assume you need some kind of image upload including image transformation (replace this with any kind of resource intensive task you can think of). Most of the time, it's not necessary to do this immediately. Even if, it doesn't help you to insist on this when you're experiencing sudden spikes in image uploads. Say this happens for like a minute, every half hour or so, so even auto-scaling would not be able to compensate. Again, Workers to the rescue. You just queue the image transformation task, let it be executed in the background by an entirely different machine. Your (web) App is still fast as usually, spike or not. Only the time an image needs to convert differs. If this image transformation is not the primary function of your App, just a mere side feature, you surely don't want it to break the rest of it! ## How does it work on fortrabbit? As you might know, every App on fortrabbit get's an SSH account. You can run your framework's CLI (or any PHP stuff you can think of), quickly pack & unpack things and so on. What you cannot do - 'till now that is - is execute long running processes. This was because our SSH nodes are shared nodes. There are many people using them at the same time. Why? Well, because of SFTP. A lot of developers are still used to (S)FTP uploading and even if you're a fanatic Git supporter, SFTP is still a good choice for some use-cases. Long running processes? What have they to do with Workers? Well, they are Workers. Any Worker, be it `artisan`'s `queue:listen` command or [Resque](https://github.com/chrisboulton/php-resque), is eventually based on an endless `while`-loop doing stuff. And an endless `while`-loop doing stuff is a long running processes per definition. So we went from there: We already had an SSH account, but it's also used for SFTP. This means minimal resources on the one hand (occasional login via SSH or uploading via SFTP) and potentially huge resource requirements on the other (eg image transforming Workers). So the solution is simple: Dedicated SSH Worker nodes for everybody who needs them, our standard SSH account for everybody else. And this are our Workers. At the moment, you can book them in three different sizes (scalable at any time later). See [pricing page](http://fortrabbit.com/pricing) for more details. ## Is there more? Sure! We've also written up a Scheduler CLI for you. With this, you can register your workers in a Scheduler server, which makes sure your workers keep running and are restarted if they should fail. Also you have easey control (eg restart on code changes, status reports, log tailing) over them and one candy at the the end: You can also schedule cron jobs. We hope you like it and give it a try. ## Further Readings * [fortrabbit docs](http://fortrabbit.com/docs/in-depth/workers-and-cron-jobs) * [Heroku docs about background tasks](https://devcenter.heroku.com/articles/background-jobs-queueing) < good explanation of the concept * [Bernard](http://bernard.readthedocs.org/en/latest/) < a task queue implemented in PHP # www Source: https://blog.fortrabbit.com/www-musings-about-a-subdomain Created: 2012-08-17 Author: Frank Lämmer Tags: opinion > The www subdomain is optional, hard to say out loud, and still everywhere. On apex domains, print designers and old internet habits. * www stands for World Wide Web and is a relict from the early internet days * . is hard to spell in english (double you, double you, double you, double you, dot) * . is just an optional subdomain * A domain without www is called apex-, naked- or bare-domain * Print designers like the look - print ads mostly include the . prefix * Young people tend to skip . when typing in a domain in the address bar of the browser * Old people always type . before they type the actual domain name * Some web masters forget to set up this subdomain > 404 * . is coming back with modern cloud hosting (CNAME records, CDNs …) Sources: [1](http://superuser.com/questions/60006/what-is-the-purpose-of-the-www-subdomain), [2](http://no-www.org/), [3](https://devcenter.heroku.com/articles/avoiding-naked-domains-dns-arecords) # New XSL support Source: https://blog.fortrabbit.com/xsl-supported-welcome-symphony-cms Created: 2013-03-10 Author: Ulrich Kautz Tags: chronicles > The PHP XSL extension is deployed across the platform, which makes Symphony CMS and its XML and XSLT templates run on fortrabbit. We're glad to announce that we've deployed the [PHP XSL extension](http://www.php.net/manual/en/book.xsl.php) today allowing you to run [Symphony CMS](http://getsymphony.com/) on fortrabbit! Symphony is a content management system powered by XML an XSLT. It's quite mature, well tested (2.0 was released in 2008, current stable is 2.3.1) and focused on simplicity in design and complete control for the developers. Symphony is completely open source, but [commercial support](http://getsymphony.com/get-support/) is offered. There is a huge set of [extensions](http://getsymphony.com/download/extensions/) and macros in form of [XSLT Utilities](http://getsymphony.com/download/xslt-utilities/). Currently, Symphony is migrating towards PHP 5.4, so there are still some quirks you have to [deal with](http://support.fortrabbit.com/customer/portal/articles/1012692-install-symphony-cms). # Yes, we rewrite Source: https://blog.fortrabbit.com/yes-we-rewrite Created: 2025-02-06 20:25:35 Author: Frank Lämmer Tags: chronicles > Rewriting a hosting platform from scratch is the mistake every essay warns about. Why fortrabbit did it anyway, and how it went. A few years back, we faced a critical decision: iterate on our existing codebase or embark on a big bang rewrite. Common advice is to iterate: > They did [...] the single worst strategic mistake that any software company can make: They decided to rewrite the code from scratch. > -Joel Spolsky 2000 ([Things You Should Never Do](https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/)) ## A tough decision We did not took it lightly. In fact, it was one of the reasons making my co-founder Oliver leave. I really do see the benefits of incremental updates: Ship features sooner, deal with a system that isn't perfect, but you know very well. Refactor, don't rewrite. Yet, I think a rewrite is necessary for us: As [DHH phrased it](https://signalvnoise.com/posts/3856-the-big-rewrite-revisited), we need to **leap not skip** ahead to achieve our vision. We need to unburden ourselves from technical constraints and legacy compatibility concerns. The existing code base is too hard to maintain and extend. A new abstraction model is required. ## Halfway there It's a very ambitious project and of course it takes much longer than anticipated. Rebuilding the entire platform while simultaneously improving it's feature set is a monumental task. There are many loose ends still. Every day new details emerge (unknown unknowns). I can see from first principle now why big rewrite projects fail. > We are writing new bugs instead of fixing old ones. It's recommended to put out a minimum viable product to gauge user interest and gather early feedback. But I feel our platform is the sum of all tightly interconnected parts and so I can not see what an MVP would look like for us. Despite a somehow sticky business model, the rewrite remains a very big gamble. This new platform needs to be the bedrock of our business for years to come. ## My take now Experience breeds wisdom, and past mistakes make us cautious. Risk aversion increases with age. However, there's also a certain naiveté that can be advantageous when embarking on a daunting endeavor. As Mark Twain quipped: > They did not know it was impossible, so they did it. The road ahead is still long and the finish line is not in sight yet. We recently restructured our roadmap and postponed some goals. On the positive side, we are now approaching an early private alpha access phase. Get in touch if you want to be one among the first adventurers. I am proud of our progress and what we have achieved so far and i'm incredibly fortunate to work with such a talented and dedicated team.