It's not easy unless you begin with that mind-set from day one.
In fact, it gets tricky as you have "location-flagged" functionality depending upon Cloud or Self-hosted.
We did this from scratch @ Documize by making (bold?) choices around deployment/runtime and database schema design for both SaaS and self-hosted "products":
- run the exact same binary (we used Golang)
- share/use the exact same database schema
- data migration process the same for schema changes
- support multi-tenanting: "enterprise" self-hosted also multi-tenanting so different teams/departments internally get different URLs
- use the same "build" process to compile and ship
Probably plenty more I could tell you!