Code of Conduct
Note: this policy applies to all AFNix project spaces and hosted communication spaces, with the following exceptions:
- The Lix Project: refer to the Lix Community Standards instead.
As with many Open Source projects, and the greater FLOSS community, AFNix projects and their communities are comprised of a diverse group of contributors and consumers from around the globe. We find the contributions, collaborations, and mentorships within our community to be the essential lifeblood of our project and appreciate the efforts of those who participate to nurture and grow those, and all other aspects of our community.
However, when a large and sufficiently diverse group of people work together, there are often cultural, communication, and compatibility issues. In order to minimize conflict, and provide a framework for resolution, we have a brief code of conduct that we ask all participants in the communities we host to adhere to. These rules should apply to everyone, regardless of station within the community, and anyone can serve to remind, or ask the Board to help resolve issues.
No list is ever exhaustive, so we encourage members of AFNix project communities to adhere to the spirit, rather than the letter, of this code, as that is how it will be enforced. Places where this code may be particularly applicable are Zulip, Forgejo, conferences, meetups, online events, and other direct interactions within the community. Any violations, especially continued or flagrant offenses, may affect an individual’s (or organization’s) ability to participate within AFNix project communities.
If you feel that someone is in violation of the code of conduct, whether in letter or in spirit, we request that you email as detailed a description as possible of the offense and offending party/parties to the AFNix Board: board@afnix.fr.
Rules
- Be friendly and patient. We were all new or suffered from a lack of knowledge at one point in time. Please try to remember what it felt like to be on that end, and treat people accordingly.
- Be welcoming. We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
- Be helpful. By helping others to learn our entire ecosystem is enriched. We encourage members of the AFNix community to mentor each other and help to raise the general level of knowledge in the community whenever possible.
- Be considerate. Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.
- Be respectful. Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the AFNix community should be respectful when dealing with other members as well as with people outside the AFNix community.
- Be careful in the words that you choose. We are a community of
professionals, and we conduct ourselves professionally. Be kind to others.
Do not insult or put down other participants. Harassment and other
exclusionary behavior aren’t acceptable. This includes, but is not limited
to:
- Violent threats or language directed against another person.
- Discriminatory jokes and language.
- Posting sexually explicit or violent material.
- Posting (or threatening to post) other people’s personally identifying information (“doxing”).
- Personal insults, especially those using racist or sexist terms.
- Unwelcome sexual attention.
- Advocating for, or encouraging, any of the above behavior.
- Repeated harassment of others. In general, if someone asks you to stop, then stop.
- When we disagree, try to understand why. Disagreements, both social and technical, happen all the time and AFNix is no exception. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of AFNix projects comes from their varied communities, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
Consequences
Infraction of these rules will lead to any combination of the following actions, at the discretion of the AFNix Board:
- A verbal warning and a request to stop the infringing behavior.
- A temporary suspension from any or all avenues of AFNix community participation. This can include, but is not limited to, Zulip, Forgejo, and/or AFNix organized events.
- A permanent suspension from AFNix communities.
Thanks to the Ceph Project and the Django Project for the original inspiration of this document, and the Ada Initiative for expanding the fight for equality and civility within FLOSS communities and beyond.
AI Usage Policy
AFNix hosted projects do not allow any contributions which are believed to include AI generated content, or to be derived from AI generated content.
Using generative AI tooling in a way that does not result in creative AI generated content appearing in the contributed work is tolerated. This includes, for example:
- AI helping summarize a documentation page to assist in developing a feature.
- AI-based assistive technology (e.g. screen reader, speech to text) leaving full creative control to the author.
- AI assisting as part of static analysis or debugging workflows.
AFNix project maintainers are requested to uphold this policy to the best of their ability: contributions which are openly or obviously in violation of this AI Usage Policy should be rejected. In doubt or in case of repeated infractions, please contact the AFNix Board.
Infractions to this policy will lead to consequences such as a warning or a suspension from AFNix projects (temporary or permanent).
AFNix Association Membership Policy
AFNix is a non-profit association following the principle of representative democracy. Members of the association regularly vote on the membership of the main decision body: the Board. Additionally, in case of dissatisfaction with the actions of the Board, members can call a vote of no-confidence to replace the roster of the Board. As such, membership in AFNix comes with a certain amount of decision power and control on the future of the association. This policy document describes the criteria defining who can join AFNix as a voting member.
Note: for more information on the democratic processes as well as other non-voting member classes (sponsoring members, emeritus members), please refer to the association's statutes.
Representatives of projects hosted by AFNix
AFNix's main reason for existence is to support the projects it hosts. However, to keep this in check, we invite projects hosted by AFNix to take place in the democratic decision making by offering each project a membership for a chosen representative. This representative is chosen by the leadership of their respective project, and can be changed at any time.
Since it is in the interest of the association to have proper representation of its hosted projects (to better reflect the needs of our users in our democratic choices, and to give the processes legitimacy), the Board is expected to regularly check that the roster of representatives does not contain inactive members. In the case of inactivity of a representative, the Board should proactively initiate talks with the respective project leadership to get a replacement.
Contributors to AFNix
Individuals who have shown significant commitment to AFNix by contributing to the operations of the association can be invited to become members by decision of the Board. The Board is expected to behave relatively openly in this regard and to award said invitations quickly once someone has shown their interest in contributing regularly to the association.
This roster of members will be regularly re-evaluated by the Board to remove members that have stopped being active. This will always be preceded by an early notice giving the member the option to continue contributing or to oppose the decision by proposing a voting motion to the association.
Contributors to the AFNix association may also be contributors to AFNix hosted projects. In this situation, we encourage said projects to name a separate representative member who is not already an AFNix contributor. This does indirectly give more democratic weight to these projects, but this is a desired outcome if their contributors are also actively helping the AFNix association with its day to day operations.
Project Eligibility Criteria
The AFNix association board decides whether a project can be onboarded on a case-by-case basis. This documentation page describes what minimal criteria need to be met for such a decision to be approved, as well as other optional elements that are desired and valued, positively influencing the board's decisions.
Meeting all these criteria is not a guarantee that onboarding will be accepted. External factors such as infrastructure capacity or concerns about the number of hosted projects also weigh in to the decisions.
If after reading this page you think that your project is a good fit for AFNix, don't hesitate to contact us.
Hard requirements
-
The Project needs to relate to Nix and its ecosystem. We take a very broad and open view of what the Nix ecosystem encompasses. Examples include: Nix language implementations, developer tooling for the Nix language, individual Nix packages or package sets, NixOS modules, Nix language libraries, software or infrastructure related to building Nix derivations, alternate Nix stores and caches implementations, and more.
-
The Project needs to be generally useful to the public. Things that are tailored to a specific individual's needs or a specific company's needs and that can't be easily generalized to other use cases are not a good fit for AFNix hosting.
-
The Project needs to agree to the relevant AFNix policies such as:
- The Code of Conduct
- The AI Usage Policy
Valuable properties
Criteria in this list are not requirements but are desired for AFNix projects. None of them are blockers individually, but a lack of adherence to many of them raises questions as to whether the Project is a good fit for AFNix.
-
The Project should be community driven, not corporate driven. While corporate contributions are welcome, we prefer the Project leadership to be mostly free of conflicts of interest, and we prefer a variety of independent entities to be in control of technical and non-technical decisions rather than a single entity.
-
The Project should be undergoing active development. There are sometimes exceptions to that rule, e.g. mature projects that require long term, reliable hosting which AFNix may be able to provide. However, we do not want to be a graveyard of dead and inactive projects.
-
AFNix expects newer Projects to have thought about the goals they want to accomplish and the scope of their work. This would traditionally take the form of a roadmap document explaining what the desired features of the Project are and what are its differentiating factors with similar projects in the ecosystem. Other forms are also acceptable, for example a list of issues on a tracker, or a release announcement blog post describing the Project.
-
AFNix expects Projects that are forks of existing projects to use an alternative branding that clearly distinguishes the fork from its upstream. It should be clear to users that the fork is a separate Project, and ideally the differentiating factors are advertised upfront to avoid any confusion.
Conventions and Guidelines
Note: this page applies to contributing to AFNix itself, not to projects hosted by AFNix, which may operate under different rules and expectations.
Contributors to AFNix are encouraged to familiarize themselves with the following guidelines and conventions that the project follows. These are not strict rules, but going against these guidelines warrants careful consideration and should ideally be justified.
General Information
-
AFNix projects are hosted on git.afnix.fr/afnix.
-
Contributors should be familiar with the Code of Conduct as well as the AI Usage Policy.
-
We encourage most changes to get code reviewed by another contributor, but do not require it for experienced contributors that have been given write access to a repository. We still expect complex, controversial, or interesting changes to get reviewed - but small or time-sensitive changes can be pushed directly.
-
When a repository has CI enabled, passing CI is a requirement for changes to be merged. Exceptions can be made if justified due to e.g. flakiness, infrastructure issues, time sensitivity, etc.
-
Project discussions are to happen in the open, not in private messages or private chat rooms. This does not mean everyone should be listened to - we in fact explicitly discourage this, and the AFNix Zulip is designed to only allow contributors and/or trusted users to talk in work-focused channels.
Velocity / Agility
-
We optimize for quick decision making, not perfect and/or consensus-based decision making. If a decision can be rolled back later, we tend to accept the risk of taking the wrong decision and having to change our minds later. Strong opinions should be expressed, but preferences are just preferences - not everyone will agree on them, and it's ok to ignore them, especially when following them requires significant work (e.g. rewriting a change).
-
We favor doing something now over blocking something until later. Small improvements can wait and be sent later as followup commits (by the author or by a reviewer). Blocking a change on technical grounds should never be done without offering a clear way forward.
-
When possible, we try to avoid roundtrips. Nitpicks and/or requests for small fixes can be given along with an approval to merge. We trust each other and do not require everything to be double-checked. Conversely, an approval means that the author of a change should feel free to merge their changes; wasting reviewer time by requiring a re-review on a typo fix is not useful to anyone.
Infrastructure Access
Access to the AFNix infrastructure comes with additional requirements in order to properly safeguard user data. We aim to keep the access control list small, adding only contributors who commit to being active contributors and have a track record proving the quality of their work.
- Only members of the AFNix Association can be granted infrastructure-level access.
- Members with infrastructure-level access are to sign a confidentiality charter reminding them of rules surrounding data access and the consequences of violating said rules.
- Access to infrastructure is granted on a temporary, renewable basis and will be regularly re-evaluated and withdrawn if unused.
A new hosted project on AFNix
Step 0: Check whether the project belongs on AFNix
AFNix hosted projects have a few requirements:
- Related to the Nix ecosystem.
- Temporary: willing to accept short-to-mid-term instability as we figure out things on the fly.
- (TODO: in compliance with our overall Code of Conduct)
- (TODO: in compliance with our overall AI Policy)
While we are bootstrapping AFNix, we also require agreement of a majority of AFNix board members to onboard a new project. This is not intended to be the final process, and we'd like more objective and/or democratic processes, but we're not set up for this yet.
Step 1: Create Forgejo org
Permissions required: Forgejo admin.
For most projects, we prefer namespacing their repository/repositories under their own org. Preferred naming convention: lowercase-dash-separated.
Create a new org on git.afnix.fr under your own user. Initially it contains your user as one of the owners of the org - this will be removed in a later step.
All org defaults can be left as-is, customization can be handled by project maintainers themselves.
Step 2: Create Keycloak group
Permissions required: Keycloak admin, AFNix Terraform access.
We track user<->project role mappings in Keycloak via a terraformed configuration.
In https://git.afnix.fr/afnix/infra/src/branch/main/terraform/afnix_superadmin/keycloak/org-groups.nix, update the memberships
attrset with the usernames of the project maintainers.
E.g. if toto
maintains the new project tata
, add underneath # Hosted projects
:
let
...
memberships = {
"afnix" = [ ... ];
# Hosted projects
...
"tata" = [ "toto" ];
};
Then, redeploy the keycloak configuration.
Step 3: Update Forgejo group/role mapping
Permissions required: AFNix infra.
In https://git.afnix.fr/afnix/infra/src/branch/main/hosts/afnix/yuki/forgejo.nix also update the initial provisioning script to match. This should be as easy as adding the org name to keycloakManagedOrgs
.
At this point, the project maintainer should be able to log out/in from git.afnix.fr and have owner permissions on the org for their project. They can create new repositories within the org and invite new collaborators.
Step 4: Optional: Add Forgejo actions runners
Permissions required: AFNix infra.
Make sure the project maintainer is aware of the limitations of the Forgejo actions runners (esp. regarding security). This should ideally be a documentation page, but we do not have it now.
Follow the template from https://git.afnix.fr/afnix/infra/commit/fee791f487b8785d4714938e4c096d89e3960cba for how to deploy new actions runners. The secret file should contain a single line of text: TOKEN=registration token value
with registration token value
being the value shown by Forgejo when going to the "Runners" tab of the Org settings page. If you are still a member of the Forgejo org, you can get it yourself, or you can ask the project maintainer to get it for you.
Don't forget to apply the changes.
Step 5: Remove yourself from the org owners
This should happen automatically on next Forgejo login, but if it doesn't: don't forget to remove yourself from the owners of the Forgejo org you created.
Migrating a virtual machine to a new hostId
This document describes how to migrate the state of a micro VM while changing the hostId
value.
This procedure is NOT required if you rename the virtual machine name.
This includes ZFS datasets and sshd state stored under /var/lib/microvms/$HOST_ID/sshd/
.
Steps
-
Snapshot the VM state (strongly recommended)
Ensure you can roll back in case of an error:
zfs snapshot rpool/<old_id>/state@pre-migration zfs snapshot rpool/<old_id>/state-journal@pre-migration
-
Stop the VM
systemctl stop microvm@$VM_NAME
-
Destroy auto-created datasets for the new host ID
If they exist, ensure they are empty or do not contain any data, destroy the empty datasets to avoid conflicts:
zfs destroy -r rpool/<new_id> || true
-
Rename the old host ID datasets to the new host ID
zfs rename rpool/<old_id> rpool/<new_id>
-
Move the sshd state directory
Ensure that the new host ID directory do not contain valuable private key material:
# If the target directory already exist, move it and clean it up at the very end. mv /var/lib/microvms/<new_id> /var/lib/microvms/unused_<new_id> mkdir -p /var/lib/microvms/<new_id> && cp -r /var/lib/microvms/<old_id> /var/lib/microvms/<new_id>
-
Start the VM
systemctl start microvm@$VM_NAME
-
Cleanup the pre-migration snapshots once data is confirmed
zfs destroy rpool/<new_id>/state@pre-migration zfs destroy rpool/<new_id>/state-journal@pre-migration
-
Cleanup the remaining sshd state
Ensure that you confirmed that the rebooted VM is using the intended sshd state.
rm -r /var/lib/microvms/unused_<new_id> rm -r /var/lib/microvms/<old_id>
Example
# Old and new host IDs
OLD_ID=9080c1b6
NEW_ID=abcd1234
# Snapshot the old datasets.
zfs snapshot rpool/$OLD_ID/state@pre-migration
zfs snapshot rpool/$OLD_ID/state-journal@pre-migration
# Stop the VM
systemctl stop microvm@vm-example
# Destroy new host datasets (if pre-created)
# Confirm that the new ID dataset do not contain important data.
zfs destroy -r rpool/$NEW_ID || true
# Rename datasets
zfs rename rpool/$OLD_ID rpool/$NEW_ID
# Replace sshd state directory, confirm that the $NEW_ID directory do not
# contain important data.
mv /var/lib/microvms/$NEW_ID /var/lib/microvms/unused_$NEWID
cp -r /var/lib/microvms/$OLD_ID /var/lib/microvms/$NEW_ID
# Restart VM
systemctl start microvm@vm-example
# Cleanup the snapshots once the data is confirmed.
zfs destroy rpool/<new_id>/state@pre-migration
zfs destroy rpool/<new_id>/state-journal@pre-migration
# Cleanup sshd state.
rm -r /var/lib/microvms/unused_$NEWID
rm -r /var/lib/microvms/$OLD_ID
Restoring the old dataset
If something goes wrong during migration, you can roll back to the original state using the snapshots created earlier.
Steps
-
Stop the VM (if running)
systemctl stop microvm@$VM_NAME
-
Rollback to the pre-migration snapshot
zfs rollback rpool/<new_id>/state@pre-migration zfs rollback rpool/<new_id>/state-journal@pre-migration
-
Restore the sshd state directory
For the old host ID, a copy still remains at the old ID address:
mv /var/lib/microvms/<new_id> /var/lib/microvms/unused2_<new_id> # skip if you are sure you do not need the current sshd state. cp -r /var/lib/microvms/<old_id> /var/lib/microvms/<new_id>
For the new host ID, a copy still remains at the unused ID address:
mv /var/lib/microvms/<new_id> /var/lib/microvms/unused2_<new_id> # skip if you are sure you do not need the current sshd state. cp -r /var/lib/microvms/unused_<new_id> /var/lib/microvms/<new_id>
-
Start the VM
systemctl start microvm@$VM_NAME